static void project_player_handler_WATER(project_player_handler_context_t *context) { /* Confusion */ (void)player_inc_timed(player, TMD_CONFUSED, 5 + randint1(5), true, true); /* Stun */ (void)player_inc_timed(player, TMD_STUN, randint1(40), true, true); }
static void project_player_handler_ICE(project_player_handler_context_t *context) { if (!player_is_immune(player, ELEM_COLD)) inven_damage(player, PROJ_COLD, MIN(context->dam * 5, 300)); /* Cuts */ if (!player_resists(player, ELEM_SHARD)) (void)player_inc_timed(player, TMD_CUT, damroll(5, 8), true, false); else msg("You resist the effect!"); /* Stun */ (void)player_inc_timed(player, TMD_STUN, randint1(15), true, true); }
static void project_player_handler_SHARD(project_player_handler_context_t *context) { /* Cuts */ if (!player_resists(player, ELEM_SHARD)) (void)player_inc_timed(player, TMD_CUT, randint1(context->dam), TRUE, FALSE); }
/** * Swap stats at random to temporarily scramble the player's stats. */ static void project_player_swap_stats(void) { int max1, cur1, max2, cur2, i, j, swap; // Fisher-Yates shuffling algorithm. for (i = STAT_MAX - 1; i > 0; --i) { j = randint0(i); max1 = player->stat_max[i]; cur1 = player->stat_cur[i]; max2 = player->stat_max[j]; cur2 = player->stat_cur[j]; player->stat_max[i] = max2; player->stat_cur[i] = cur2; player->stat_max[j] = max1; player->stat_cur[j] = cur1; /* Record what we did */ swap = player->stat_map[i]; player->stat_map[i] = player->stat_map[j]; player->stat_map[j] = swap; } player_inc_timed(player, TMD_SCRAMBLE, randint0(20) + 20, true, true); return; }
/** * Do damage as the result of a melee attack that has a status effect. * * \param context is the information for the current attack. * \param type is the TMD_ constant for the effect. * \param amount is the amount that the timer should be increased by. * \param of_flag is the OF_ flag that is passed on to monster learning for * this effect. * \param attempt_save indicates if a saving throw should be attempted for * this effect. * \param save_msg is the message that is displayed if the saving throw is * successful. */ static void melee_effect_timed(melee_effect_handler_context_t *context, int type, int amount, int of_flag, bool attempt_save, const char *save_msg) { /* Take damage */ take_hit(context->p, context->damage, context->ddesc); /* Player is dead */ if (context->p->is_dead) return; /* Perform a saving throw if desired. */ if (attempt_save && randint0(100) < context->p->state.skills[SKILL_SAVE]) { if (save_msg != NULL) msg("%s", save_msg); context->obvious = TRUE; } else { /* Increase timer for type. */ if (player_inc_timed(context->p, type, amount, TRUE, TRUE)) context->obvious = TRUE; } /* Learn about the player */ update_smart_learn(context->mon, context->p, of_flag, 0, -1); }
static void project_player_handler_LIGHT(project_player_handler_context_t *context) { if (player_resists(player, ELEM_LIGHT)) { msg("You resist the effect!"); return; } (void)player_inc_timed(player, TMD_BLIND, 2 + randint1(5), TRUE, TRUE); }
static void project_player_handler_DARK_WEAK(project_player_handler_context_t *context) { if (player_resists(player, ELEM_DARK)) { msg("You resist the effect!"); return; } (void)player_inc_timed(player, TMD_BLIND, 3 + randint1(5), true, true); }
static void project_player_handler_PLASMA(project_player_handler_context_t *context) { /* Stun */ if (!player_of_has(player, OF_PROT_STUN)) { int duration = 5 + randint1(context->dam * 3 / 4); if (duration > 35) duration = 35; (void)player_inc_timed(player, TMD_STUN, duration, TRUE, TRUE); } }
static void project_player_handler_CHAOS(project_player_handler_context_t *context) { if (player_resists(player, ELEM_CHAOS)) { msg("You resist the effect!"); return; } /* Hallucination */ (void)player_inc_timed(player, TMD_IMAGE, randint1(10), TRUE, FALSE); /* Confusion */ (void)player_inc_timed(player, TMD_CONFUSED, 10 + randint0(20), TRUE, TRUE); /* Life draining */ if (player_of_has(player, OF_HOLD_LIFE)) { msg("You feel your life force draining away!"); player_exp_lose(player, 5000 + (player->exp / 100) * z_info->life_drain_percent, FALSE); } }
static void project_player_handler_GRAVITY(project_player_handler_context_t *context) { msg("Gravity warps around you."); /* Blink */ if (randint1(127) > player->lev) { const char *five = "5"; effect_simple(EF_TELEPORT, five, 0, 1, 0, NULL); } /* Slow */ (void)player_inc_timed(player, TMD_SLOW, 4 + randint0(4), TRUE, FALSE); /* Stun */ if (!player_of_has(player, OF_PROT_STUN)) { int duration = 5 + randint1(context->dam / 3); if (duration > 35) duration = 35; (void)player_inc_timed(player, TMD_STUN, duration, TRUE, TRUE); } }
static void project_player_handler_SHARD(project_player_handler_context_t *context) { if (player_resists(player, ELEM_SHARD)) { msg("You resist the effect!"); return; } /* Cuts */ (void)player_inc_timed(player, TMD_CUT, randint1(context->dam), true, false); }
static void project_player_handler_FORCE(project_player_handler_context_t *context) { char grids_away[5]; /* Stun */ (void)player_inc_timed(player, TMD_STUN, randint1(20), true, true); /* Thrust player away. */ strnfmt(grids_away, sizeof(grids_away), "%d", 3 + context->dam / 20); effect_simple(EF_THRUST_AWAY, context->origin, grids_away, context->y, context->x, 0, NULL); }
/** * Melee effect handler: Poison the player. * * We can't use melee_effect_timed(), because this is both and elemental attack * and a status attack. Note the FALSE value for pure_element for * melee_effect_elemental(). */ static void melee_effect_handler_POISON(melee_effect_handler_context_t *context) { melee_effect_elemental(context, GF_POIS, FALSE); /* Take "poison" effect */ if (player_inc_timed(context->p, TMD_POISONED, 5 + randint1(context->rlev), TRUE, TRUE)) context->obvious = TRUE; /* Learn about the player */ update_smart_learn(context->m_ptr, context->p, 0, 0, ELEM_POIS); }
/** * Melee effect handler: Make the player hallucinate. * * Note that we don't use melee_effect_timed(), due to the different monster * learning function. */ static void melee_effect_handler_HALLU(melee_effect_handler_context_t *context) { /* Take damage */ take_hit(context->p, context->damage, context->ddesc); /* Increase "image" */ if (player_inc_timed(context->p, TMD_IMAGE, 3 + randint1(context->rlev / 2), TRUE, TRUE)) context->obvious = TRUE; /* Learn about the player */ update_smart_learn(context->m_ptr, context->p, 0, 0, ELEM_CHAOS); }
static void project_player_handler_SOUND(project_player_handler_context_t *context) { if (player_resists(player, ELEM_SOUND)) { msg("You resist the effect!"); return; } /* Stun */ if (!player_of_has(player, OF_PROT_STUN)) { int duration = 5 + randint1(context->dam / 3); if (duration > 35) duration = 35; (void)player_inc_timed(player, TMD_STUN, duration, TRUE, TRUE); } }
/** * Melee effect handler: Poison the player. * * We can't use melee_effect_timed(), because this is both and elemental attack * and a status attack. Note the false value for pure_element for * melee_effect_elemental(). */ static void melee_effect_handler_POISON(melee_effect_handler_context_t *context) { melee_effect_elemental(context, GF_POIS, false); /* Player is dead */ if (context->p->is_dead) return; /* Take "poison" effect */ if (player_inc_timed(context->p, TMD_POISONED, 5 + randint1(context->rlev), true, true)) context->obvious = true; /* Learn about the player */ update_smart_learn(context->mon, context->p, 0, 0, ELEM_POIS); }
/** * Melee effect handler: Make the player hallucinate. * * Note that we don't use melee_effect_timed(), due to the different monster * learning function. */ static void melee_effect_handler_HALLU(melee_effect_handler_context_t *context) { /* Take damage */ take_hit(context->p, context->damage, context->ddesc); /* Player is dead */ if (context->p->is_dead) return; /* Increase "image" */ if (player_inc_timed(context->p, TMD_IMAGE, 3 + randint1(context->rlev / 2), true, true)) context->obvious = true; /* Learn about the player */ update_smart_learn(context->mon, context->p, 0, 0, ELEM_CHAOS); }
/** * Attack the player via physical attacks. */ bool make_attack_normal(struct monster *mon, struct player *p) { struct monster_lore *lore = get_lore(mon->race); int ap_cnt; int k, tmp, ac, rlev; char m_name[80]; char ddesc[80]; bool blinked; /* Not allowed to attack */ if (rf_has(mon->race->flags, RF_NEVER_BLOW)) return (false); /* Total armor */ ac = p->state.ac + p->state.to_a; /* Extract the effective monster level */ rlev = ((mon->race->level >= 1) ? mon->race->level : 1); /* Get the monster name (or "it") */ monster_desc(m_name, sizeof(m_name), mon, MDESC_STANDARD); /* Get the "died from" information (i.e. "a kobold") */ monster_desc(ddesc, sizeof(ddesc), mon, MDESC_SHOW | MDESC_IND_VIS); /* Assume no blink */ blinked = false; /* Scan through all blows */ for (ap_cnt = 0; ap_cnt < z_info->mon_blows_max; ap_cnt++) { bool visible = false; bool obvious = false; bool do_break = false; int power = 0; int damage = 0; int do_cut = 0; int do_stun = 0; int sound_msg = MSG_GENERIC; const char *act = NULL; /* Extract the attack infomation */ int effect = mon->race->blow[ap_cnt].effect; int method = mon->race->blow[ap_cnt].method; random_value dice = mon->race->blow[ap_cnt].dice; /* Hack -- no more attacks */ if (!method) break; /* Handle "leaving" */ if (p->is_dead || p->upkeep->generate_level) break; /* Extract visibility (before blink) */ if (mflag_has(mon->mflag, MFLAG_VISIBLE)) visible = true; /* Extract visibility from carrying light */ if (rf_has(mon->race->flags, RF_HAS_LIGHT)) visible = true; /* Extract the attack "power" */ power = monster_blow_effect_power(effect); /* Monster hits player */ if (!effect || check_hit(p, power, rlev)) { melee_effect_handler_f effect_handler; /* Always disturbing */ disturb(p, 1); /* Hack -- Apply "protection from evil" */ if (p->timed[TMD_PROTEVIL] > 0) { /* Learn about the evil flag */ if (mflag_has(mon->mflag, MFLAG_VISIBLE)) rf_on(lore->flags, RF_EVIL); if (rf_has(mon->race->flags, RF_EVIL) && p->lev >= rlev && randint0(100) + p->lev > 50) { /* Message */ msg("%s is repelled.", m_name); /* Hack -- Next attack */ continue; } } /* Describe the attack method */ act = monster_blow_method_action(method); do_cut = monster_blow_method_cut(method); do_stun = monster_blow_method_stun(method); sound_msg = monster_blow_method_message(method); /* Message */ if (act) msgt(sound_msg, "%s %s", m_name, act); /* Hack -- assume all attacks are obvious */ obvious = true; /* Roll dice */ damage = randcalc(dice, rlev, RANDOMISE); /* Perform the actual effect. */ effect_handler = melee_handler_for_blow_effect(effect); if (effect_handler != NULL) { melee_effect_handler_context_t context = { p, mon, rlev, method, ac, ddesc, obvious, blinked, do_break, damage, }; effect_handler(&context); /* Save any changes made in the handler for later use. */ obvious = context.obvious; blinked = context.blinked; damage = context.damage; do_break = context.do_break; } else { msg("ERROR: Effect handler not found for %d.", effect); } /* Don't cut or stun if player is dead */ if (p->is_dead) { do_cut = false; do_stun = false; } /* Hack -- only one of cut or stun */ if (do_cut && do_stun) { /* Cancel cut */ if (randint0(100) < 50) do_cut = 0; /* Cancel stun */ else do_stun = 0; } /* Handle cut */ if (do_cut) { /* Critical hit (zero if non-critical) */ tmp = monster_critical(dice, rlev, damage); /* Roll for damage */ switch (tmp) { case 0: k = 0; break; case 1: k = randint1(5); break; case 2: k = randint1(5) + 5; break; case 3: k = randint1(20) + 20; break; case 4: k = randint1(50) + 50; break; case 5: k = randint1(100) + 100; break; case 6: k = 300; break; default: k = 500; break; } /* Apply the cut */ if (k) (void)player_inc_timed(p, TMD_CUT, k, true, true); } /* Handle stun */ if (do_stun) { /* Critical hit (zero if non-critical) */ tmp = monster_critical(dice, rlev, damage); /* Roll for damage */ switch (tmp) { case 0: k = 0; break; case 1: k = randint1(5); break; case 2: k = randint1(10) + 10; break; case 3: k = randint1(20) + 20; break; case 4: k = randint1(30) + 30; break; case 5: k = randint1(40) + 40; break; case 6: k = 100; break; default: k = 200; break; } /* Apply the stun */ if (k) (void)player_inc_timed(p, TMD_STUN, k, true, true); } } else { /* Visible monster missed player, so notify if appropriate. */ if (mflag_has(mon->mflag, MFLAG_VISIBLE) && monster_blow_method_miss(method)) { /* Disturbing */ disturb(p, 1); msg("%s misses you.", m_name); } } /* Analyze "visible" monsters only */ if (visible) { /* Count "obvious" attacks (and ones that cause damage) */ if (obvious || damage || (lore->blows[ap_cnt].times_seen > 10)) { /* Count attacks of this type */ if (lore->blows[ap_cnt].times_seen < UCHAR_MAX) lore->blows[ap_cnt].times_seen++; } } /* Skip the other blows if necessary */ if (do_break) break; } /* Blink away */ if (blinked) { char dice[5]; msg("There is a puff of smoke!"); strnfmt(dice, sizeof(dice), "%d", z_info->max_sight * 2 + 5); effect_simple(EF_TELEPORT, dice, 0, 0, 0, NULL); } /* Always notice cause of death */ if (p->is_dead && (lore->deaths < SHRT_MAX)) lore->deaths++; /* Learn lore */ lore_update(mon->race, lore); /* Assume we attacked */ return (true); }
/** * Apply side effects from a spell attack to the player * * \param spell is the attack type * \param dam is the amount of damage caused by the attack * \param m_idx is the attacking monster * \param rlev is its level * \param seen is whether @ can see it */ static void do_side_effects(int spell, int dam, int m_idx, bool seen) { monster_type *m_ptr = cave_monster(cave, m_idx); monster_race *r_ptr = &r_info[m_ptr->r_idx]; const struct spell_effect *re_ptr; const struct mon_spell *rs_ptr = &mon_spell_table[spell]; int i, choice[99], dur = 0, j = 0, count = 0; s32b d = 0; bool sustain = FALSE, perma = FALSE, chosen[RSE_MAX] = { 0 }; /* Extract the monster level */ int rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1); /* First we note all the effects we'll be doing. */ for (re_ptr = spell_effect_table; re_ptr->index < RSE_MAX; re_ptr++) { if ((re_ptr->method && (re_ptr->method == rs_ptr->index)) || (re_ptr->gf && (re_ptr->gf == rs_ptr->gf))) { /* If we have a choice of effects, we create a cum freq table */ if (re_ptr->chance) { for (i = j; i < (j + re_ptr->chance); i++) choice[i] = re_ptr->index; j = i; } else chosen[re_ptr->index] = TRUE; } } /* If we have built a cum freq table, choose an effect from it */ if (j) chosen[choice[randint0(j)]] = TRUE; /* Now we cycle through again to activate the chosen effects */ for (re_ptr = spell_effect_table; re_ptr->index < RSE_MAX; re_ptr++) { if (chosen[re_ptr->index]) { /* * Check for resistance - there are three possibilities: * 1. Immunity to the attack type if side_immune is TRUE * 2. Resistance to the attack type if it affords no immunity * 3. Resistance to the specific side-effect * * TODO - add interesting messages to the RSE_ and GF_ tables * to replace the generic ones below. (See #1376) */ if (re_ptr->res_flag) update_smart_learn(m_ptr, p_ptr, re_ptr->res_flag); if ((rs_ptr->gf && check_side_immune(rs_ptr->gf)) || check_state(p_ptr, re_ptr->res_flag, p_ptr->state.flags)) { msg("You resist the effect!"); continue; } /* Allow saving throw if available */ if (re_ptr->save && randint0(100) < p_ptr->state.skills[SKILL_SAVE]) { msg("You avoid the effect!"); continue; } /* Implement the effect */ if (re_ptr->timed) { /* Calculate base duration (m_bonus is not used) */ dur = randcalc(re_ptr->base, 0, RANDOMISE); /* Calculate the damage-dependent duration (m_bonus is * used as a cap) */ dur += damcalc(re_ptr->dam.dice, re_ptr->dam.sides * dam / 100, RANDOMISE); if (re_ptr->dam.m_bonus && (dur > re_ptr->dam.m_bonus)) dur = re_ptr->dam.m_bonus; /* Apply the effect - we have already checked for resistance */ (void)player_inc_timed(p_ptr, re_ptr->flag, dur, TRUE, FALSE); } else { switch (re_ptr->flag) { case S_INV_DAM: if (dam > 0) inven_damage(p_ptr, re_ptr->gf, MIN(dam * randcalc(re_ptr->dam, 0, RANDOMISE), 300)); break; case S_TELEPORT: /* m_bonus is used as a clev filter */ if (!re_ptr->dam.m_bonus || randint1(re_ptr->dam.m_bonus) > p_ptr->lev) teleport_player(randcalc(re_ptr->base, 0, RANDOMISE)); break; case S_TELE_TO: teleport_player_to(m_ptr->fy, m_ptr->fx); break; case S_TELE_LEV: teleport_player_level(); break; case S_TELE_SELF: teleport_away(m_ptr, randcalc(re_ptr->base, 0, RANDOMISE)); break; case S_DRAIN_LIFE: d = re_ptr->base.base + (p_ptr->exp * re_ptr->base.sides / 100) * MON_DRAIN_LIFE; msg("You feel your life force draining away!"); player_exp_lose(p_ptr, d, FALSE); break; case S_DRAIN_STAT: /* m_bonus is used as a flag */ if (re_ptr->dam.m_bonus > 0) sustain = TRUE; if (abs(re_ptr->dam.m_bonus) > 1) perma = TRUE; drain_stats(randcalc(re_ptr->base, 0, RANDOMISE), sustain, perma); break; case S_SWAP_STAT: swap_stats(); break; case S_DRAIN_ALL: msg("You're not as powerful as you used to be..."); for (i = 0; i < A_MAX; i++) player_stat_dec(p_ptr, i, FALSE); break; case S_DISEN: (void)apply_disenchant(0); break; case S_DRAIN_MANA: drain_mana(m_idx, rlev, seen); break; case S_HEAL: heal_self(m_idx, rlev, seen); break; case S_DARKEN: (void)unlight_area(0, 3); break; case S_TRAPS: (void)trap_creation(); break; case S_AGGRAVATE: aggravate_monsters(m_idx); break; case S_KIN: summon_kin_type = r_ptr->d_char; case S_MONSTER: case S_MONSTERS: case S_SPIDER: case S_HOUND: case S_HYDRA: case S_AINU: case S_ANIMAL: case S_DEMON: case S_HI_DEMON: case S_UNDEAD: case S_HI_UNDEAD: case S_WRAITH: case S_DRAGON: case S_HI_DRAGON: case S_UNIQUE: count = summon_monster_aux(re_ptr->flag, m_idx, rlev, re_ptr->base.base); /* In the special case that uniques or wraiths were summoned but all were dead S_HI_UNDEAD is used instead */ if ((!count) && ((re_ptr->flag == S_WRAITH) || (re_ptr->flag == S_UNIQUE))) count = summon_monster_aux(S_HI_UNDEAD, m_idx, rlev, re_ptr->base.base); if (count && p_ptr->timed[TMD_BLIND]) msgt(rs_ptr->msgt, "You hear %s appear nearby.", (count > 1 ? "many things" : "something")); default: break; } } } } return; }
static bool cast_mage_spell(int spell, int dir) { int py = p_ptr->py; int px = p_ptr->px; int plev = p_ptr->lev; /* Hack -- chance of "beam" instead of "bolt" */ int beam = beam_chance(); /* Spells. */ switch (spell) { case SPELL_MAGIC_MISSILE: { fire_bolt_or_beam(beam-10, GF_MISSILE, dir, damroll(3 + ((plev - 1) / 5), 4)); break; } case SPELL_DETECT_MONSTERS: { (void)detect_monsters_normal(TRUE); break; } case SPELL_PHASE_DOOR: { teleport_player(10); break; } case SPELL_LIGHT_AREA: { (void)light_area(damroll(2, (plev / 2)), (plev / 10) + 1); break; } case SPELL_OBJECT_DETECTION: { (void)detect_treasure(TRUE, TRUE); break; } case SPELL_CURE_LIGHT_WOUNDS: { heal_player(15, 15); player_dec_timed(p_ptr, TMD_CUT, 20, TRUE); player_dec_timed(p_ptr, TMD_CONFUSED, 20, TRUE); player_clear_timed(p_ptr, TMD_BLIND, TRUE); break; } case SPELL_FIND_TRAPS_DOORS: { (void)detect_traps(TRUE); (void)detect_doorstairs(TRUE); break; } case SPELL_STINKING_CLOUD: { fire_ball(GF_POIS, dir, 10 + (plev / 2), 2); break; } case SPELL_CONFUSE_MONSTER: { (void)confuse_monster(dir, plev, TRUE); break; } case SPELL_LIGHTNING_BOLT: { fire_beam(GF_ELEC, dir, damroll(3+((plev-5)/6), 6)); break; } case SPELL_TRAP_DOOR_DESTRUCTION: { (void)destroy_doors_touch(); break; } case SPELL_SLEEP_MONSTER: { (void)sleep_monster(dir, TRUE); break; } case SPELL_CURE_POISON: { (void)player_clear_timed(p_ptr, TMD_POISONED, TRUE); break; } case SPELL_TELEPORT_SELF: { teleport_player(plev * 5); break; } case SPELL_SPEAR_OF_LIGHT: { msg("A line of blue shimmering light appears."); light_line(dir); break; } case SPELL_FROST_BOLT: { fire_bolt_or_beam(beam-10, GF_COLD, dir, damroll(5+((plev-5)/4), 8)); break; } case SPELL_TURN_STONE_TO_MUD: { (void)wall_to_mud(dir); break; } case SPELL_SATISFY_HUNGER: { player_set_food(p_ptr, PY_FOOD_MAX - 1); break; } case SPELL_RECHARGE_ITEM_I: { return recharge(2 + plev / 5); } case SPELL_WONDER: { (void)spell_wonder(dir); break; } case SPELL_POLYMORPH_OTHER: { (void)poly_monster(dir); break; } case SPELL_IDENTIFY: { return ident_spell(); } case SPELL_MASS_SLEEP: { (void)sleep_monsters(TRUE); break; } case SPELL_FIRE_BOLT: { fire_bolt_or_beam(beam, GF_FIRE, dir, damroll(6+((plev-5)/4), 8)); break; } case SPELL_SLOW_MONSTER: { (void)slow_monster(dir); break; } case SPELL_FROST_BALL: { fire_ball(GF_COLD, dir, 30 + (plev), 2); break; } case SPELL_RECHARGE_ITEM_II: /* greater recharging */ { return recharge(50 + plev); } case SPELL_TELEPORT_OTHER: { (void)teleport_monster(dir); break; } case SPELL_BEDLAM: { fire_ball(GF_OLD_CONF, dir, plev, 4); break; } case SPELL_FIRE_BALL: { fire_ball(GF_FIRE, dir, 55 + (plev), 2); break; } case SPELL_WORD_OF_DESTRUCTION: { destroy_area(py, px, 15, TRUE); break; } case SPELL_BANISHMENT: { return banishment(); } case SPELL_DOOR_CREATION: { (void)door_creation(); break; } case SPELL_STAIR_CREATION: { (void)stair_creation(); break; } case SPELL_TELEPORT_LEVEL: { (void)teleport_player_level(); break; } case SPELL_EARTHQUAKE: { earthquake(py, px, 10); break; } case SPELL_WORD_OF_RECALL: { return set_recall(); } case SPELL_ACID_BOLT: { fire_bolt_or_beam(beam, GF_ACID, dir, damroll(8+((plev-5)/4), 8)); break; } case SPELL_CLOUD_KILL: { fire_ball(GF_POIS, dir, 40 + (plev / 2), 3); break; } case SPELL_ACID_BALL: { fire_ball(GF_ACID, dir, 40 + (plev), 2); break; } case SPELL_ICE_STORM: { fire_ball(GF_ICE, dir, 50 + (plev * 2), 3); break; } case SPELL_METEOR_SWARM: { fire_swarm(2 + plev / 20, GF_METEOR, dir, 30 + plev / 2, 1); break; } case SPELL_MANA_STORM: { fire_ball(GF_MANA, dir, 300 + (plev * 2), 3); break; } case SPELL_DETECT_INVISIBLE: { (void)detect_monsters_normal(TRUE); (void)detect_monsters_invis(TRUE); break; } case SPELL_TREASURE_DETECTION: { (void)detect_treasure(TRUE, FALSE); break; } case SPELL_SHOCK_WAVE: { fire_ball(GF_SOUND, dir, 10 + plev, 2); break; } case SPELL_EXPLOSION: { fire_ball(GF_SHARD, dir, 20 + (plev * 2), 2); break; } case SPELL_MASS_BANISHMENT: { (void)mass_banishment(); break; } case SPELL_RESIST_FIRE: { (void)player_inc_timed(p_ptr, TMD_OPP_FIRE, randint1(20) + 20, TRUE, TRUE); break; } case SPELL_RESIST_COLD: { (void)player_inc_timed(p_ptr, TMD_OPP_COLD, randint1(20) + 20, TRUE, TRUE); break; } case SPELL_ELEMENTAL_BRAND: /* elemental brand */ { return brand_ammo(); } case SPELL_RESIST_POISON: { (void)player_inc_timed(p_ptr, TMD_OPP_POIS, randint1(20) + 20, TRUE, TRUE); break; } case SPELL_RESISTANCE: { int time = randint1(20) + 20; (void)player_inc_timed(p_ptr, TMD_OPP_ACID, time, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_OPP_ELEC, time, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_OPP_FIRE, time, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_OPP_COLD, time, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_OPP_POIS, time, TRUE, TRUE); break; } case SPELL_HEROISM: { int dur = randint1(25) + 25; (void)hp_player(10); (void)player_clear_timed(p_ptr, TMD_AFRAID, TRUE); (void)player_inc_timed(p_ptr, TMD_BOLD, dur, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_HERO, dur, TRUE, TRUE); break; } case SPELL_SHIELD: { (void)player_inc_timed(p_ptr, TMD_SHIELD, randint1(20) + 30, TRUE, TRUE); break; } case SPELL_BERSERKER: { int dur = randint1(25) + 25; (void)hp_player(30); (void)player_clear_timed(p_ptr, TMD_AFRAID, TRUE); (void)player_inc_timed(p_ptr, TMD_BOLD, dur, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_SHERO, dur, TRUE, TRUE); break; } case SPELL_HASTE_SELF: { if (!p_ptr->timed[TMD_FAST]) { (void)player_set_timed(p_ptr, TMD_FAST, randint1(20) + plev, TRUE); } else { (void)player_inc_timed(p_ptr, TMD_FAST, randint1(5), TRUE, TRUE); } break; } case SPELL_RIFT: { fire_beam(GF_GRAVITY, dir, 40 + damroll(plev, 7)); break; } case SPELL_REND_SOUL: /* rend soul */ { fire_bolt_or_beam(beam / 4, GF_NETHER, dir, damroll(11, plev)); break; } case SPELL_CHAOS_STRIKE: /* chaos strike */ { fire_bolt_or_beam(beam, GF_CHAOS, dir, damroll(13, plev)); break; } case SPELL_RUNE_OF_PROTECTION: /* rune of protection */ { warding_glyph_spell(); break; } case SPELL_ENCHANT_ARMOR: /* enchant armor */ { return enchant_spell(0, 0, randint0(3) + plev / 20); } case SPELL_ENCHANT_WEAPON: /* enchant weapon */ { return enchant_spell(randint0(4) + plev / 20, randint0(4) + plev / 20, 0); } } /* Success */ return (TRUE); }
static bool cast_priest_spell(int spell, int dir) { int py = p_ptr->py; int px = p_ptr->px; int plev = p_ptr->lev; int amt; switch (spell) { case PRAYER_DETECT_EVIL: { (void)detect_monsters_evil(TRUE); break; } case PRAYER_CURE_LIGHT_WOUNDS: { (void)heal_player(15, 15); (void)player_dec_timed(p_ptr, TMD_CUT, 20, TRUE); (void)player_dec_timed(p_ptr, TMD_CONFUSED, 20, TRUE); (void)player_clear_timed(p_ptr, TMD_BLIND, TRUE); break; } case PRAYER_BLESS: { (void)player_inc_timed(p_ptr, TMD_BLESSED, randint1(12) + 12, TRUE, TRUE); break; } case PRAYER_REMOVE_FEAR: { (void)player_clear_timed(p_ptr, TMD_AFRAID, TRUE); break; } case PRAYER_CALL_LIGHT: { (void)light_area(damroll(2, (plev / 2)), (plev / 10) + 1); break; } case PRAYER_FIND_TRAPS_DOORS: { (void)detect_traps(TRUE); (void)detect_doorstairs(TRUE); break; } case PRAYER_SLOW_POISON: { (void)player_set_timed(p_ptr, TMD_POISONED, p_ptr->timed[TMD_POISONED] / 2, TRUE); break; } case PRAYER_SCARE_MONSTER: { (void)fear_monster(dir, plev, TRUE); break; } case PRAYER_PORTAL: { teleport_player(plev * 3); break; } case PRAYER_CURE_SERIOUS_WOUNDS: { (void)heal_player(20, 25); (void)player_clear_timed(p_ptr, TMD_CUT, TRUE); (void)player_clear_timed(p_ptr, TMD_CONFUSED, TRUE); (void)player_clear_timed(p_ptr, TMD_BLIND, TRUE); break; } case PRAYER_CHANT: { (void)player_inc_timed(p_ptr, TMD_BLESSED, randint1(24) + 24, TRUE, TRUE); break; } case PRAYER_SANCTUARY: { (void)sleep_monsters_touch(TRUE); break; } case PRAYER_SATISFY_HUNGER: { player_set_food(p_ptr, PY_FOOD_MAX - 1); break; } /* Remove curse has been removed in 3.4 until curses are redone case PRAYER_REMOVE_CURSE: { remove_curse(); break; } */ case PRAYER_RESIST_HEAT_COLD: { (void)player_inc_timed(p_ptr, TMD_OPP_FIRE, randint1(10) + 10, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_OPP_COLD, randint1(10) + 10, TRUE, TRUE); break; } case PRAYER_NEUTRALIZE_POISON: { (void)player_clear_timed(p_ptr, TMD_POISONED, TRUE); break; } case PRAYER_ORB_OF_DRAINING: { fire_ball(GF_HOLY_ORB, dir, (damroll(3, 6) + plev + (player_has(PF_ZERO_FAIL) ? (plev / 2) : (plev / 4))), ((plev < 30) ? 2 : 3)); break; } case PRAYER_CURE_CRITICAL_WOUNDS: { (void)heal_player(25, 30); (void)player_clear_timed(p_ptr, TMD_CUT, TRUE); (void)player_clear_timed(p_ptr, TMD_AMNESIA, TRUE); (void)player_clear_timed(p_ptr, TMD_CONFUSED, TRUE); (void)player_clear_timed(p_ptr, TMD_BLIND, TRUE); (void)player_clear_timed(p_ptr, TMD_POISONED, TRUE); (void)player_clear_timed(p_ptr, TMD_STUN, TRUE); break; } case PRAYER_SENSE_INVISIBLE: { (void)player_inc_timed(p_ptr, TMD_SINVIS, randint1(24) + 24, TRUE, TRUE); break; } case PRAYER_PROTECTION_FROM_EVIL: { (void)player_inc_timed(p_ptr, TMD_PROTEVIL, randint1(25) + 3 * p_ptr->lev, TRUE, TRUE); break; } case PRAYER_EARTHQUAKE: { earthquake(py, px, 10); break; } case PRAYER_SENSE_SURROUNDINGS: { map_area(); break; } case PRAYER_CURE_MORTAL_WOUNDS: { (void)heal_player(30, 50); (void)player_clear_timed(p_ptr, TMD_CUT, TRUE); (void)player_clear_timed(p_ptr, TMD_AMNESIA, TRUE); (void)player_clear_timed(p_ptr, TMD_CONFUSED, TRUE); (void)player_clear_timed(p_ptr, TMD_BLIND, TRUE); (void)player_clear_timed(p_ptr, TMD_POISONED, TRUE); (void)player_clear_timed(p_ptr, TMD_STUN, TRUE); break; } case PRAYER_TURN_UNDEAD: { (void)turn_undead(TRUE); break; } case PRAYER_PRAYER: { (void)player_inc_timed(p_ptr, TMD_BLESSED, randint1(48) + 48, TRUE, TRUE); break; } case PRAYER_DISPEL_UNDEAD: { (void)dispel_undead(randint1(plev * 3)); break; } case PRAYER_HEAL: { amt = (p_ptr->mhp * 35) / 100; if (amt < 300) amt = 300; (void)hp_player(amt); (void)player_clear_timed(p_ptr, TMD_CUT, TRUE); (void)player_clear_timed(p_ptr, TMD_AMNESIA, TRUE); (void)player_clear_timed(p_ptr, TMD_CONFUSED, TRUE); (void)player_clear_timed(p_ptr, TMD_BLIND, TRUE); (void)player_clear_timed(p_ptr, TMD_POISONED, TRUE); (void)player_clear_timed(p_ptr, TMD_STUN, TRUE); break; } case PRAYER_DISPEL_EVIL: { (void)dispel_evil(randint1(plev * 3)); break; } case PRAYER_GLYPH_OF_WARDING: { warding_glyph_spell(); break; } case PRAYER_HOLY_WORD: { (void)dispel_evil(randint1(plev * 4)); (void)hp_player(1000); (void)player_clear_timed(p_ptr, TMD_AFRAID, TRUE); (void)player_clear_timed(p_ptr, TMD_POISONED, TRUE); (void)player_clear_timed(p_ptr, TMD_STUN, TRUE); (void)player_clear_timed(p_ptr, TMD_CUT, TRUE); break; } case PRAYER_DETECT_MONSTERS: { (void)detect_monsters_normal(TRUE); break; } case PRAYER_DETECTION: { (void)detect_all(TRUE); break; } case PRAYER_PERCEPTION: { return ident_spell(); } case PRAYER_PROBING: { (void)probing(); break; } case PRAYER_CLAIRVOYANCE: { wiz_light(FALSE); break; } case PRAYER_CURE_SERIOUS_WOUNDS2: { (void)heal_player(20, 25); (void)player_clear_timed(p_ptr, TMD_CUT, TRUE); (void)player_clear_timed(p_ptr, TMD_CONFUSED, TRUE); (void)player_clear_timed(p_ptr, TMD_BLIND, TRUE); break; } case PRAYER_CURE_MORTAL_WOUNDS2: { (void)heal_player(30, 50); (void)player_clear_timed(p_ptr, TMD_CUT, TRUE); (void)player_clear_timed(p_ptr, TMD_AMNESIA, TRUE); (void)player_clear_timed(p_ptr, TMD_CONFUSED, TRUE); (void)player_clear_timed(p_ptr, TMD_BLIND, TRUE); (void)player_clear_timed(p_ptr, TMD_POISONED, TRUE); (void)player_clear_timed(p_ptr, TMD_STUN, TRUE); break; } case PRAYER_HEALING: { (void)hp_player(2000); (void)player_clear_timed(p_ptr, TMD_STUN, TRUE); (void)player_clear_timed(p_ptr, TMD_CUT, TRUE); break; } case PRAYER_RESTORATION: { (void)do_res_stat(A_STR); (void)do_res_stat(A_INT); (void)do_res_stat(A_WIS); (void)do_res_stat(A_DEX); (void)do_res_stat(A_CON); break; } case PRAYER_REMEMBRANCE: { (void)restore_level(); break; } case PRAYER_DISPEL_UNDEAD2: { (void)dispel_undead(randint1(plev * 4)); break; } case PRAYER_DISPEL_EVIL2: { (void)dispel_evil(randint1(plev * 4)); break; } case PRAYER_BANISH_EVIL: { if (banish_evil(100)) { msg("The power of your god banishes evil!"); } break; } case PRAYER_WORD_OF_DESTRUCTION: { destroy_area(py, px, 15, TRUE); break; } case PRAYER_ANNIHILATION: { drain_life(dir, 200); break; } case PRAYER_UNBARRING_WAYS: { (void)destroy_doors_touch(); break; } case PRAYER_RECHARGING: { return recharge(20 + plev); } /* Dispel Curse has been removed in 3.4 until curses are redone case PRAYER_DISPEL_CURSE: { (void)remove_all_curse(); break; } */ case PRAYER_ENCHANT_WEAPON: { return enchant_spell(randint0(4) + 1, randint0(4) + 1, 0); } case PRAYER_ENCHANT_ARMOUR: { return enchant_spell(0, 0, randint0(3) + 2); } case PRAYER_ELEMENTAL_BRAND: { brand_weapon(); break; } case PRAYER_BLINK: { teleport_player(10); break; } case PRAYER_TELEPORT_SELF: { teleport_player(plev * 8); break; } case PRAYER_TELEPORT_OTHER: { (void)teleport_monster(dir); break; } case PRAYER_TELEPORT_LEVEL: { (void)teleport_player_level(); break; } case PRAYER_WORD_OF_RECALL: { return set_recall(); } case PRAYER_ALTER_REALITY: { msg("The world changes!"); /* Leaving */ p_ptr->leaving = TRUE; break; } } /* Success */ return (TRUE); }
static void project_player_handler_INERTIA(project_player_handler_context_t *context) { /* Slow */ (void)player_inc_timed(player, TMD_SLOW, 4 + randint0(4), true, false); }
/* * Do an effect, given an object. * Boost is the extent to which skill surpasses difficulty, used as % boost. It * ranges from 0 to 138. */ bool effect_do(effect_type effect, bool *ident, bool aware, int dir, int beam, int boost) { int py = p_ptr->py; int px = p_ptr->px; int dam, chance, dur; if (effect < 1 || effect > EF_MAX) { msg("Bad effect passed to do_effect(). Please report this bug."); return FALSE; } switch (effect) { case EF_POISON: { player_inc_timed(p_ptr, TMD_POISONED, damroll(2, 7) + 10, TRUE, TRUE); *ident = TRUE; return TRUE; } case EF_BLIND: { player_inc_timed(p_ptr, TMD_BLIND, damroll(4, 25) + 75, TRUE, TRUE); *ident = TRUE; return TRUE; } case EF_SCARE: { player_inc_timed(p_ptr, TMD_AFRAID, randint0(10) + 10, TRUE, TRUE); *ident = TRUE; return TRUE; } case EF_CONFUSE: { player_inc_timed(p_ptr, TMD_CONFUSED, damroll(4, 5) + 10, TRUE, TRUE); *ident = TRUE; return TRUE; } case EF_HALLUC: { player_inc_timed(p_ptr, TMD_IMAGE, randint0(250) + 250, TRUE, TRUE); *ident = TRUE; return TRUE; } case EF_PARALYZE: { player_inc_timed(p_ptr, TMD_PARALYZED, randint0(5) + 5, TRUE, TRUE); *ident = TRUE; return TRUE; } case EF_SLOW: { if (player_inc_timed(p_ptr, TMD_SLOW, randint1(25) + 15, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_CURE_POISON: { if (player_clear_timed(p_ptr, TMD_POISONED, TRUE)) *ident = TRUE; return TRUE; } case EF_CURE_BLINDNESS: { if (player_clear_timed(p_ptr, TMD_BLIND, TRUE)) *ident = TRUE; return TRUE; } case EF_CURE_PARANOIA: { if (player_clear_timed(p_ptr, TMD_AFRAID, TRUE)) *ident = TRUE; return TRUE; } case EF_CURE_CONFUSION: { if (player_clear_timed(p_ptr, TMD_CONFUSED, TRUE)) *ident = TRUE; return TRUE; } case EF_CURE_MIND: { if (player_clear_timed(p_ptr, TMD_CONFUSED, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_AFRAID, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_IMAGE, TRUE)) *ident = TRUE; if (!of_has(p_ptr->state.flags, OF_RES_CONFU) && player_inc_timed(p_ptr, TMD_OPP_CONF, damroll(4, 10), TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_CURE_BODY: { if (player_clear_timed(p_ptr, TMD_STUN, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CUT, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_POISONED, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_BLIND, TRUE)) *ident = TRUE; return TRUE; } case EF_CURE_LIGHT: { if (hp_player(20)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_BLIND, TRUE)) *ident = TRUE; if (player_dec_timed(p_ptr, TMD_CUT, 20, TRUE)) *ident = TRUE; if (player_dec_timed(p_ptr, TMD_CONFUSED, 20, TRUE)) *ident = TRUE; return TRUE; } case EF_CURE_SERIOUS: { if (hp_player(40)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CUT, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_BLIND, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CONFUSED, TRUE)) *ident = TRUE; return TRUE; } case EF_CURE_CRITICAL: { if (hp_player(60)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_BLIND, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CONFUSED, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_POISONED, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_STUN, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CUT, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_AMNESIA, TRUE)) *ident = TRUE; return TRUE; } case EF_CURE_FULL: { int amt = (p_ptr->mhp * 35) / 100; if (amt < 300) amt = 300; if (hp_player(amt)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_BLIND, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CONFUSED, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_POISONED, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_STUN, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CUT, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_AMNESIA, TRUE)) *ident = TRUE; return TRUE; } case EF_CURE_FULL2: { if (hp_player(1200)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_BLIND, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CONFUSED, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_POISONED, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_STUN, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CUT, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_AMNESIA, TRUE)) *ident = TRUE; return TRUE; } case EF_CURE_TEMP: { if (player_clear_timed(p_ptr, TMD_BLIND, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_POISONED, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CONFUSED, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_STUN, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CUT, TRUE)) *ident = TRUE; return TRUE; } case EF_HEAL1: { if (hp_player(500)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CUT, TRUE)) *ident = TRUE; return TRUE; } case EF_HEAL2: { if (hp_player(1000)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CUT, TRUE)) *ident = TRUE; return TRUE; } case EF_HEAL3: { if (hp_player(500)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_STUN, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CUT, TRUE)) *ident = TRUE; return TRUE; } case EF_GAIN_EXP: { if (p_ptr->exp < PY_MAX_EXP) { msg("You feel more experienced."); player_exp_gain(p_ptr, 100000L); *ident = TRUE; } return TRUE; } case EF_LOSE_EXP: { if (!check_state(p_ptr, OF_HOLD_LIFE, p_ptr->state.flags) && (p_ptr->exp > 0)) { msg("You feel your memories fade."); player_exp_lose(p_ptr, p_ptr->exp / 4, FALSE); *ident = TRUE; } *ident = TRUE; wieldeds_notice_flag(p_ptr, OF_HOLD_LIFE); return TRUE; } case EF_RESTORE_EXP: { if (restore_level()) *ident = TRUE; return TRUE; } case EF_RESTORE_MANA: { if (p_ptr->csp < p_ptr->msp) { p_ptr->csp = p_ptr->msp; p_ptr->csp_frac = 0; msg("Your feel your head clear."); p_ptr->redraw |= (PR_MANA); *ident = TRUE; } return TRUE; } case EF_GAIN_STR: case EF_GAIN_INT: case EF_GAIN_WIS: case EF_GAIN_DEX: case EF_GAIN_CON: case EF_GAIN_CHR: { int stat = effect - EF_GAIN_STR; if (do_inc_stat(stat)) *ident = TRUE; return TRUE; } case EF_GAIN_ALL: { if (do_inc_stat(A_STR)) *ident = TRUE; if (do_inc_stat(A_INT)) *ident = TRUE; if (do_inc_stat(A_WIS)) *ident = TRUE; if (do_inc_stat(A_DEX)) *ident = TRUE; if (do_inc_stat(A_CON)) *ident = TRUE; if (do_inc_stat(A_CHR)) *ident = TRUE; return TRUE; } case EF_BRAWN: { /* Pick a random stat to decrease other than strength */ int stat = randint0(A_MAX-1) + 1; if (do_dec_stat(stat, TRUE)) { do_inc_stat(A_STR); *ident = TRUE; } return TRUE; } case EF_INTELLECT: { /* Pick a random stat to decrease other than intelligence */ int stat = randint0(A_MAX-1); if (stat >= A_INT) stat++; if (do_dec_stat(stat, TRUE)) { do_inc_stat(A_INT); *ident = TRUE; } return TRUE; } case EF_CONTEMPLATION: { /* Pick a random stat to decrease other than wisdom */ int stat = randint0(A_MAX-1); if (stat >= A_WIS) stat++; if (do_dec_stat(stat, TRUE)) { do_inc_stat(A_WIS); *ident = TRUE; } return TRUE; } case EF_TOUGHNESS: { /* Pick a random stat to decrease other than constitution */ int stat = randint0(A_MAX-1); if (stat >= A_CON) stat++; if (do_dec_stat(stat, TRUE)) { do_inc_stat(A_CON); *ident = TRUE; } return TRUE; } case EF_NIMBLENESS: { /* Pick a random stat to decrease other than dexterity */ int stat = randint0(A_MAX-1); if (stat >= A_DEX) stat++; if (do_dec_stat(stat, TRUE)) { do_inc_stat(A_DEX); *ident = TRUE; } return TRUE; } case EF_PLEASING: { /* Pick a random stat to decrease other than charisma */ int stat = randint0(A_MAX-1); if (do_dec_stat(stat, TRUE)) { do_inc_stat(A_CHR); *ident = TRUE; } return TRUE; } case EF_LOSE_STR: case EF_LOSE_INT: case EF_LOSE_WIS: case EF_LOSE_DEX: case EF_LOSE_CON: case EF_LOSE_CHR: { int stat = effect - EF_LOSE_STR; take_hit(p_ptr, damroll(5, 5), "stat drain"); (void)do_dec_stat(stat, FALSE); *ident = TRUE; return TRUE; } case EF_LOSE_CON2: { take_hit(p_ptr, damroll(10, 10), "poisonous food"); (void)do_dec_stat(A_CON, FALSE); *ident = TRUE; return TRUE; } case EF_RESTORE_STR: case EF_RESTORE_INT: case EF_RESTORE_WIS: case EF_RESTORE_DEX: case EF_RESTORE_CON: case EF_RESTORE_CHR: { int stat = effect - EF_RESTORE_STR; if (do_res_stat(stat)) *ident = TRUE; return TRUE; } case EF_CURE_NONORLYBIG: { msg("You feel life flow through your body!"); restore_level(); (void)player_clear_timed(p_ptr, TMD_POISONED, TRUE); (void)player_clear_timed(p_ptr, TMD_BLIND, TRUE); (void)player_clear_timed(p_ptr, TMD_CONFUSED, TRUE); (void)player_clear_timed(p_ptr, TMD_IMAGE, TRUE); (void)player_clear_timed(p_ptr, TMD_STUN, TRUE); (void)player_clear_timed(p_ptr, TMD_CUT, TRUE); (void)player_clear_timed(p_ptr, TMD_AMNESIA, TRUE); if (do_res_stat(A_STR)) *ident = TRUE; if (do_res_stat(A_INT)) *ident = TRUE; if (do_res_stat(A_WIS)) *ident = TRUE; if (do_res_stat(A_DEX)) *ident = TRUE; if (do_res_stat(A_CON)) *ident = TRUE; if (do_res_stat(A_CHR)) *ident = TRUE; /* Recalculate max. hitpoints */ update_stuff(p_ptr); hp_player(5000); *ident = TRUE; return TRUE; } case EF_RESTORE_ALL: { /* Life, above, also gives these effects */ if (do_res_stat(A_STR)) *ident = TRUE; if (do_res_stat(A_INT)) *ident = TRUE; if (do_res_stat(A_WIS)) *ident = TRUE; if (do_res_stat(A_DEX)) *ident = TRUE; if (do_res_stat(A_CON)) *ident = TRUE; if (do_res_stat(A_CHR)) *ident = TRUE; return TRUE; } case EF_RESTORE_ST_LEV: { if (restore_level()) *ident = TRUE; if (do_res_stat(A_STR)) *ident = TRUE; if (do_res_stat(A_INT)) *ident = TRUE; if (do_res_stat(A_WIS)) *ident = TRUE; if (do_res_stat(A_DEX)) *ident = TRUE; if (do_res_stat(A_CON)) *ident = TRUE; if (do_res_stat(A_CHR)) *ident = TRUE; return TRUE; } case EF_TMD_INFRA: { if (player_inc_timed(p_ptr, TMD_SINFRA, 100 + damroll(4, 25), TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_TMD_SINVIS: { if (player_clear_timed(p_ptr, TMD_BLIND, TRUE)) *ident = TRUE; if (player_inc_timed(p_ptr, TMD_SINVIS, 12 + damroll(2, 6), TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_TMD_ESP: { if (player_clear_timed(p_ptr, TMD_BLIND, TRUE)) *ident = TRUE; if (player_inc_timed(p_ptr, TMD_TELEPATHY, 12 + damroll(6, 6), TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_ENLIGHTENMENT: { msg("An image of your surroundings forms in your mind..."); wiz_light(); *ident = TRUE; return TRUE; } case EF_ENLIGHTENMENT2: { msg("You begin to feel more enlightened..."); message_flush(); wiz_light(); (void)do_inc_stat(A_INT); (void)do_inc_stat(A_WIS); (void)detect_traps(TRUE); (void)detect_doorstairs(TRUE); (void)detect_treasure(TRUE, TRUE); identify_pack(); *ident = TRUE; return TRUE; } case EF_HERO: { dur = randint1(25) + 25; if (hp_player(10)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_AFRAID, TRUE)) *ident = TRUE; if (player_inc_timed(p_ptr, TMD_BOLD, dur, TRUE, TRUE)) *ident = TRUE; if (player_inc_timed(p_ptr, TMD_HERO, dur, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_SHERO: { dur = randint1(25) + 25; if (hp_player(30)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_AFRAID, TRUE)) *ident = TRUE; if (player_inc_timed(p_ptr, TMD_BOLD, dur, TRUE, TRUE)) *ident = TRUE; if (player_inc_timed(p_ptr, TMD_SHERO, dur, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_RESIST_ACID: { if (player_inc_timed(p_ptr, TMD_OPP_ACID, randint1(10) + 10, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_RESIST_ELEC: { if (player_inc_timed(p_ptr, TMD_OPP_ELEC, randint1(10) + 10, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_RESIST_FIRE: { if (player_inc_timed(p_ptr, TMD_OPP_FIRE, randint1(10) + 10, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_RESIST_COLD: { if (player_inc_timed(p_ptr, TMD_OPP_COLD, randint1(10) + 10, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_RESIST_POIS: { if (player_inc_timed(p_ptr, TMD_OPP_POIS, randint1(10) + 10, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_RESIST_ALL: { if (player_inc_timed(p_ptr, TMD_OPP_ACID, randint1(20) + 20, TRUE, TRUE)) *ident = TRUE; if (player_inc_timed(p_ptr, TMD_OPP_ELEC, randint1(20) + 20, TRUE, TRUE)) *ident = TRUE; if (player_inc_timed(p_ptr, TMD_OPP_FIRE, randint1(20) + 20, TRUE, TRUE)) *ident = TRUE; if (player_inc_timed(p_ptr, TMD_OPP_COLD, randint1(20) + 20, TRUE, TRUE)) *ident = TRUE; if (player_inc_timed(p_ptr, TMD_OPP_POIS, randint1(20) + 20, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_DETECT_TREASURE: { if (detect_treasure(aware, FALSE)) *ident = TRUE; return TRUE; } case EF_DETECT_TRAP: { if (detect_traps(aware)) *ident = TRUE; return TRUE; } case EF_DETECT_DOORSTAIR: { if (detect_doorstairs(aware)) *ident = TRUE; return TRUE; } case EF_DETECT_INVIS: { if (detect_monsters_invis(aware)) *ident = TRUE; return TRUE; } case EF_DETECT_EVIL: { if (detect_monsters_evil(aware)) *ident = TRUE; return TRUE; } case EF_DETECT_ALL: { if (detect_all(aware)) *ident = TRUE; return TRUE; } case EF_ENCHANT_TOHIT: { *ident = TRUE; return enchant_spell(1, 0, 0); } case EF_ENCHANT_TODAM: { *ident = TRUE; return enchant_spell(0, 1, 0); } case EF_ENCHANT_WEAPON: { *ident = TRUE; return enchant_spell(randint1(3), randint1(3), 0); } case EF_ENCHANT_ARMOR: { *ident = TRUE; return enchant_spell(0, 0, 1); } case EF_ENCHANT_ARMOR2: { *ident = TRUE; return enchant_spell(0, 0, randint1(3) + 2); } case EF_RESTORE_ITEM: { *ident = TRUE; return restore_item(); } case EF_IDENTIFY: { *ident = TRUE; if (!ident_spell()) return FALSE; return TRUE; } case EF_REMOVE_CURSE: { if (remove_curse()) { if (!p_ptr->timed[TMD_BLIND]) msg("The air around your body glows blue for a moment..."); else msg("You feel as if someone is watching over you."); *ident = TRUE; } return TRUE; } case EF_REMOVE_CURSE2: { remove_all_curse(); *ident = TRUE; return TRUE; } case EF_LIGHT: { if (light_area(damroll(2, 8), 2)) *ident = TRUE; return TRUE; } case EF_SUMMON_MON: { int i; sound(MSG_SUM_MONSTER); for (i = 0; i < randint1(3); i++) { if (summon_specific(py, px, p_ptr->depth, 0, 1)) *ident = TRUE; } return TRUE; } case EF_SUMMON_UNDEAD: { int i; sound(MSG_SUM_UNDEAD); for (i = 0; i < randint1(3); i++) { if (summon_specific(py, px, p_ptr->depth, S_UNDEAD, 1)) *ident = TRUE; } return TRUE; } case EF_TELE_PHASE: { teleport_player(10); *ident = TRUE; return TRUE; } case EF_TELE_LONG: { teleport_player(100); *ident = TRUE; return TRUE; } case EF_TELE_LEVEL: { (void)teleport_player_level(); *ident = TRUE; return TRUE; } case EF_CONFUSING: { if (p_ptr->confusing == 0) { msg("Your hands begin to glow."); p_ptr->confusing = TRUE; *ident = TRUE; } return TRUE; } case EF_MAPPING: { map_area(); *ident = TRUE; return TRUE; } case EF_RUNE: { warding_glyph(); *ident = TRUE; return TRUE; } case EF_ACQUIRE: { acquirement(py, px, p_ptr->depth, 1, TRUE); *ident = TRUE; return TRUE; } case EF_ACQUIRE2: { acquirement(py, px, p_ptr->depth, randint1(2) + 1, TRUE); *ident = TRUE; return TRUE; } case EF_ANNOY_MON: { msg("There is a high pitched humming noise."); aggravate_monsters(0); *ident = TRUE; return TRUE; } case EF_CREATE_TRAP: { /* Hack -- no traps in the town */ if (p_ptr->depth == 0) return TRUE; trap_creation(); msg("You hear a low-pitched whistling sound."); *ident = TRUE; return TRUE; } case EF_DESTROY_TDOORS: { if (destroy_doors_touch()) *ident = TRUE; return TRUE; } case EF_RECHARGE: { *ident = TRUE; if (!recharge(60)) return FALSE; return TRUE; } case EF_BANISHMENT: { *ident = TRUE; if (!banishment()) return FALSE; return TRUE; } case EF_DARKNESS: { if (!check_state(p_ptr, OF_RES_DARK, p_ptr->state.flags)) (void)player_inc_timed(p_ptr, TMD_BLIND, 3 + randint1(5), TRUE, TRUE); unlight_area(10, 3); wieldeds_notice_flag(p_ptr, OF_RES_DARK); *ident = TRUE; return TRUE; } case EF_PROTEVIL: { if (player_inc_timed(p_ptr, TMD_PROTEVIL, randint1(25) + 3 * p_ptr->lev, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_SATISFY: { if (player_set_food(p_ptr, PY_FOOD_MAX - 1)) *ident = TRUE; return TRUE; } case EF_CURSE_WEAPON: { if (curse_weapon()) *ident = TRUE; return TRUE; } case EF_CURSE_ARMOR: { if (curse_armor()) *ident = TRUE; return TRUE; } case EF_BLESSING: { if (player_inc_timed(p_ptr, TMD_BLESSED, randint1(12) + 6, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_BLESSING2: { if (player_inc_timed(p_ptr, TMD_BLESSED, randint1(24) + 12, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_BLESSING3: { if (player_inc_timed(p_ptr, TMD_BLESSED, randint1(48) + 24, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_RECALL: { set_recall(); *ident = TRUE; return TRUE; } case EF_DEEP_DESCENT: { int i, target_depth = p_ptr->depth; /* Calculate target depth */ for (i = 5; i > 0; i--) { if (is_quest(target_depth)) break; if (target_depth >= MAX_DEPTH - 1) break; target_depth++; } if (target_depth > p_ptr->depth) { msgt(MSG_TPLEVEL, "The air around you starts to swirl..."); p_ptr->deep_descent = 3 + randint1(4); *ident = TRUE; return TRUE; } else { msgt(MSG_TPLEVEL, "You sense a malevolent presence blocking passage to the levels below."); *ident = TRUE; return FALSE; } } case EF_LOSHASTE: { if (speed_monsters()) *ident = TRUE; return TRUE; } case EF_LOSSLEEP: { if (sleep_monsters(aware)) *ident = TRUE; return TRUE; } case EF_LOSSLOW: { if (slow_monsters()) *ident = TRUE; return TRUE; } case EF_LOSCONF: { if (confuse_monsters(aware)) *ident = TRUE; return TRUE; } case EF_LOSKILL: { (void)mass_banishment(); *ident = TRUE; return TRUE; } case EF_EARTHQUAKES: { earthquake(py, px, 10); *ident = TRUE; return TRUE; } case EF_DESTRUCTION2: { destroy_area(py, px, 15, TRUE); *ident = TRUE; return TRUE; } case EF_ILLUMINATION: { if (light_area(damroll(2, 15), 3)) *ident = TRUE; return TRUE; } case EF_CLAIRVOYANCE: { *ident = TRUE; wiz_light(); (void)detect_traps(TRUE); (void)detect_doorstairs(TRUE); return TRUE; } case EF_PROBING: { *ident = probing(); return TRUE; } case EF_STONE_TO_MUD: { if (wall_to_mud(dir)) *ident = TRUE; return TRUE; } case EF_CONFUSE2: { *ident = TRUE; confuse_monster(dir, 20, aware); return TRUE; } case EF_BIZARRE: { *ident = TRUE; ring_of_power(dir); return TRUE; } case EF_STAR_BALL: { int i; *ident = TRUE; for (i = 0; i < 8; i++) fire_ball(GF_ELEC, ddd[i], (150 * (100 + boost) / 100), 3); return TRUE; } case EF_RAGE_BLESS_RESIST: { dur = randint1(50) + 50; *ident = TRUE; (void)hp_player(30); (void)player_clear_timed(p_ptr, TMD_AFRAID, TRUE); (void)player_inc_timed(p_ptr, TMD_BOLD, dur, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_SHERO, dur, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_BLESSED, randint1(50) + 50, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_OPP_ACID, randint1(50) + 50, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_OPP_ELEC, randint1(50) + 50, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_OPP_FIRE, randint1(50) + 50, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_OPP_COLD, randint1(50) + 50, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_OPP_POIS, randint1(50) + 50, TRUE, TRUE); return TRUE; } case EF_SLEEPII: { *ident = TRUE; sleep_monsters_touch(aware); return TRUE; } case EF_RESTORE_LIFE: { *ident = TRUE; restore_level(); return TRUE; } case EF_MISSILE: { *ident = TRUE; dam = damroll(3, 4) * (100 + boost) / 100; fire_bolt_or_beam(beam, GF_MISSILE, dir, dam); return TRUE; } case EF_DISPEL_EVIL: { *ident = TRUE; dam = p_ptr->lev * 5 * (100 + boost) / 100; dispel_evil(dam); return TRUE; } case EF_DISPEL_EVIL60: { dam = 60 * (100 + boost) / 100; if (dispel_evil(dam)) *ident = TRUE; return TRUE; } case EF_DISPEL_UNDEAD: { dam = 60 * (100 + boost) / 100; if (dispel_undead(dam)) *ident = TRUE; return TRUE; } case EF_DISPEL_ALL: { dam = 120 * (100 + boost) / 100; if (dispel_monsters(dam)) *ident = TRUE; return TRUE; } case EF_HASTE: { if (!p_ptr->timed[TMD_FAST]) { if (player_set_timed(p_ptr, TMD_FAST, damroll(2, 10) + 20, TRUE)) *ident = TRUE; } else { (void)player_inc_timed(p_ptr, TMD_FAST, 5, TRUE, TRUE); } return TRUE; } case EF_HASTE1: { if (!p_ptr->timed[TMD_FAST]) { if (player_set_timed(p_ptr, TMD_FAST, randint1(20) + 20, TRUE)) *ident = TRUE; } else { (void)player_inc_timed(p_ptr, TMD_FAST, 5, TRUE, TRUE); } return TRUE; } case EF_HASTE2: { if (!p_ptr->timed[TMD_FAST]) { if (player_set_timed(p_ptr, TMD_FAST, randint1(75) + 75, TRUE)) *ident = TRUE; } else { (void)player_inc_timed(p_ptr, TMD_FAST, 5, TRUE, TRUE); } return TRUE; } case EF_FIRE_BOLT: { *ident = TRUE; dam = damroll(9, 8) * (100 + boost) / 100; fire_bolt(GF_FIRE, dir, dam); return TRUE; } case EF_FIRE_BOLT2: { dam = damroll(12, 8) * (100 + boost) / 100; fire_bolt_or_beam(beam, GF_FIRE, dir, dam); *ident = TRUE; return TRUE; } case EF_FIRE_BOLT3: { dam = damroll(16, 8) * (100 + boost) / 100; fire_bolt_or_beam(beam, GF_FIRE, dir, dam); *ident = TRUE; return TRUE; } case EF_FIRE_BOLT72: { dam = 72 * (100 + boost) / 100; *ident = TRUE; fire_ball(GF_FIRE, dir, dam, 2); return TRUE; } case EF_FIRE_BALL: { dam = 144 * (100 + boost) / 100; fire_ball(GF_FIRE, dir, dam, 2); *ident = TRUE; return TRUE; } case EF_FIRE_BALL2: { dam = 120 * (100 + boost) / 100; *ident = TRUE; fire_ball(GF_FIRE, dir, dam, 3); return TRUE; } case EF_FIRE_BALL200: { dam = 200 * (100 + boost) / 100; *ident = TRUE; fire_ball(GF_FIRE, dir, dam, 3); return TRUE; } case EF_COLD_BOLT: { dam = damroll(6, 8) * (100 + boost) / 100; *ident = TRUE; fire_bolt_or_beam(beam, GF_COLD, dir, dam); return TRUE; } case EF_COLD_BOLT2: { dam = damroll(12, 8) * (100 + boost) / 100; *ident = TRUE; fire_bolt(GF_COLD, dir, dam); return TRUE; } case EF_COLD_BALL2: { dam = 200 * (100 + boost) / 100; *ident = TRUE; fire_ball(GF_COLD, dir, dam, 3); return TRUE; } case EF_COLD_BALL50: { dam = 50 * (100 + boost) / 100; *ident = TRUE; fire_ball(GF_COLD, dir, dam, 2); return TRUE; } case EF_COLD_BALL100: { dam = 100 * (100 + boost) / 100; *ident = TRUE; fire_ball(GF_COLD, dir, dam, 2); return TRUE; } case EF_COLD_BALL160: { dam = 160 * (100 + boost) / 100; *ident = TRUE; fire_ball(GF_COLD, dir, dam, 3); return TRUE; } case EF_ACID_BOLT: { dam = damroll(5, 8) * (100 + boost) / 100; *ident = TRUE; fire_bolt(GF_ACID, dir, dam); return TRUE; } case EF_ACID_BOLT2: { dam = damroll(10, 8) * (100 + boost) / 100; fire_bolt_or_beam(beam, GF_ACID, dir, dam); *ident = TRUE; return TRUE; } case EF_ACID_BOLT3: { dam = damroll(12, 8) * (100 + boost) / 100; fire_bolt_or_beam(beam, GF_ACID, dir, dam); *ident = TRUE; return TRUE; } case EF_ACID_BALL: { dam = 120 * (100 + boost) / 100; fire_ball(GF_ACID, dir, dam, 2); *ident = TRUE; return TRUE; } case EF_ELEC_BOLT: { dam = damroll(6, 6) * (100 + boost) / 100; *ident = TRUE; fire_beam(GF_ELEC, dir, dam); return TRUE; } case EF_ELEC_BALL: { dam = 64 * (100 + boost) / 100; fire_ball(GF_ELEC, dir, dam, 2); *ident = TRUE; return TRUE; } case EF_ELEC_BALL2: { dam = 250 * (100 + boost) / 100; *ident = TRUE; fire_ball(GF_ELEC, dir, dam, 3); return TRUE; } case EF_ARROW: { dam = 150 * (100 + boost) / 100; *ident = TRUE; fire_bolt(GF_ARROW, dir, dam); return TRUE; } case EF_REM_FEAR_POIS: { *ident = TRUE; (void)player_clear_timed(p_ptr, TMD_AFRAID, TRUE); (void)player_clear_timed(p_ptr, TMD_POISONED, TRUE); return TRUE; } case EF_STINKING_CLOUD: { dam = 12 * (100 + boost) / 100; *ident = TRUE; fire_ball(GF_POIS, dir, dam, 3); return TRUE; } case EF_DRAIN_LIFE1: { dam = 90 * (100 + boost) / 100; if (drain_life(dir, dam)) *ident = TRUE; return TRUE; } case EF_DRAIN_LIFE2: { dam = 120 * (100 + boost) / 100; if (drain_life(dir, dam)) *ident = TRUE; return TRUE; } case EF_DRAIN_LIFE3: { dam = 150 * (100 + boost) / 100; if (drain_life(dir, dam)) *ident = TRUE; return TRUE; } case EF_DRAIN_LIFE4: { dam = 250 * (100 + boost) / 100; if (drain_life(dir, dam)) *ident = TRUE; return TRUE; } case EF_FIREBRAND: { *ident = TRUE; if (!brand_bolts()) return FALSE; return TRUE; } case EF_MANA_BOLT: { dam = damroll(12, 8) * (100 + boost) / 100; fire_bolt(GF_MANA, dir, dam); *ident = TRUE; return TRUE; } case EF_MON_HEAL: { if (heal_monster(dir)) *ident = TRUE; return TRUE; } case EF_MON_HASTE: { if (speed_monster(dir)) *ident = TRUE; return TRUE; } case EF_MON_SLOW: { if (slow_monster(dir)) *ident = TRUE; return TRUE; } case EF_MON_CONFUSE: { if (confuse_monster(dir, 10, aware)) *ident = TRUE; return TRUE; } case EF_MON_SLEEP: { if (sleep_monster(dir, aware)) *ident = TRUE; return TRUE; } case EF_MON_CLONE: { if (clone_monster(dir)) *ident = TRUE; return TRUE; } case EF_MON_SCARE: { if (fear_monster(dir, 10, aware)) *ident = TRUE; return TRUE; } case EF_LIGHT_LINE: { msg("A line of shimmering blue light appears."); light_line(dir); *ident = TRUE; return TRUE; } case EF_TELE_OTHER: { if (teleport_monster(dir)) *ident = TRUE; return TRUE; } case EF_DISARMING: { if (disarm_trap(dir)) *ident = TRUE; return TRUE; } case EF_TDOOR_DEST: { if (destroy_door(dir)) *ident = TRUE; return TRUE; } case EF_POLYMORPH: { if (poly_monster(dir)) *ident = TRUE; return TRUE; } case EF_STARLIGHT: { int i; if (!p_ptr->timed[TMD_BLIND]) msg("Light shoots in all directions!"); for (i = 0; i < 8; i++) light_line(ddd[i]); *ident = TRUE; return TRUE; } case EF_STARLIGHT2: { int k; for (k = 0; k < 8; k++) strong_light_line(ddd[k]); *ident = TRUE; return TRUE; } case EF_BERSERKER: { dur = randint1(50) + 50; if (player_inc_timed(p_ptr, TMD_BOLD, dur, TRUE, TRUE)) *ident = TRUE; if (player_inc_timed(p_ptr, TMD_SHERO, dur, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_SUN_HERO: { (void)light_area(damroll(20, 10), 8); dur = randint1(25) + 25; if (player_inc_timed(p_ptr, TMD_BOLD, dur, TRUE, TRUE)) *ident = TRUE; if (player_inc_timed(p_ptr, TMD_SHERO, dur, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_WONDER: { if (effect_wonder(dir, randint1(100) + p_ptr->lev / 5, beam)) *ident = TRUE; return TRUE; } case EF_WAND_BREATH: { /* table of random ball effects and their damages */ const int breath_types[] = { GF_ACID, 200, GF_ELEC, 160, GF_FIRE, 200, GF_COLD, 160, GF_POIS, 120 }; /* pick a random (type, damage) tuple in the table */ int which = 2 * randint0(sizeof(breath_types) / (2 * sizeof(int))); fire_ball(breath_types[which], dir, breath_types[which + 1], 3); *ident = TRUE; return TRUE; } case EF_STAFF_MAGI: { if (do_res_stat(A_INT)) *ident = TRUE; if (p_ptr->csp < p_ptr->msp) { p_ptr->csp = p_ptr->msp; p_ptr->csp_frac = 0; *ident = TRUE; msg("Your feel your head clear."); p_ptr->redraw |= (PR_MANA); } return TRUE; } case EF_STAFF_HOLY: { dam = 120 * (100 + boost) / 100; if (dispel_evil(dam)) *ident = TRUE; if (player_inc_timed(p_ptr, TMD_PROTEVIL, randint1(25) + 3 * p_ptr->lev, TRUE, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_POISONED, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_AFRAID, TRUE)) *ident = TRUE; if (hp_player(50)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_STUN, TRUE)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_CUT, TRUE)) *ident = TRUE; return TRUE; } case EF_DRINK_BREATH: { const int breath_types[] = { GF_FIRE, 80, GF_COLD, 80, }; int which = 2 * randint0(N_ELEMENTS(breath_types) / 2); fire_ball(breath_types[which], dir, breath_types[which + 1], 2); *ident = TRUE; return TRUE; } case EF_DRINK_GOOD: { msg("You feel less thirsty."); *ident = TRUE; return TRUE; } case EF_DRINK_DEATH: { msg("A feeling of Death flows through your body."); take_hit(p_ptr, 5000, "a potion of Death"); *ident = TRUE; return TRUE; } case EF_DRINK_RUIN: { msg("Your nerves and muscles feel weak and lifeless!"); take_hit(p_ptr, damroll(10, 10), "a potion of Ruination"); player_stat_dec(p_ptr, A_DEX, TRUE); player_stat_dec(p_ptr, A_WIS, TRUE); player_stat_dec(p_ptr, A_CON, TRUE); player_stat_dec(p_ptr, A_STR, TRUE); player_stat_dec(p_ptr, A_CHR, TRUE); player_stat_dec(p_ptr, A_INT, TRUE); *ident = TRUE; return TRUE; } case EF_DRINK_DETONATE: { msg("Massive explosions rupture your body!"); take_hit(p_ptr, damroll(50, 20), "a potion of Detonation"); (void)player_inc_timed(p_ptr, TMD_STUN, 75, TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_CUT, 5000, TRUE, TRUE); *ident = TRUE; return TRUE; } case EF_DRINK_SALT: { msg("The potion makes you vomit!"); player_set_food(p_ptr, PY_FOOD_STARVE - 1); (void)player_clear_timed(p_ptr, TMD_POISONED, TRUE); (void)player_inc_timed(p_ptr, TMD_PARALYZED, 4, TRUE, FALSE); *ident = TRUE; return TRUE; } case EF_FOOD_GOOD: { msg("That tastes good."); *ident = TRUE; return TRUE; } case EF_FOOD_WAYBREAD: { msg("That tastes good."); (void)player_clear_timed(p_ptr, TMD_POISONED, TRUE); (void)hp_player(damroll(4, 8)); *ident = TRUE; return TRUE; } case EF_SHROOM_EMERGENCY: { (void)player_set_timed(p_ptr, TMD_IMAGE, rand_spread(250, 50), TRUE); (void)player_set_timed(p_ptr, TMD_OPP_FIRE, rand_spread(30, 10), TRUE); (void)player_set_timed(p_ptr, TMD_OPP_COLD, rand_spread(30, 10), TRUE); (void)hp_player(200); *ident = TRUE; return TRUE; } case EF_SHROOM_TERROR: { if (player_set_timed(p_ptr, TMD_TERROR, rand_spread(100, 20), TRUE)) *ident = TRUE; return TRUE; } case EF_SHROOM_STONE: { if (player_set_timed(p_ptr, TMD_STONESKIN, rand_spread(80, 20), TRUE)) *ident = TRUE; return TRUE; } case EF_SHROOM_DEBILITY: { int stat = one_in_(2) ? A_STR : A_CON; if (p_ptr->csp < p_ptr->msp) { p_ptr->csp = p_ptr->msp; p_ptr->csp_frac = 0; msg("Your feel your head clear."); p_ptr->redraw |= (PR_MANA); *ident = TRUE; } (void)do_dec_stat(stat, FALSE); *ident = TRUE; return TRUE; } case EF_SHROOM_SPRINTING: { if (player_inc_timed(p_ptr, TMD_SPRINT, 100, TRUE, TRUE)) *ident = TRUE; return TRUE; } case EF_SHROOM_PURGING: { player_set_food(p_ptr, PY_FOOD_FAINT - 1); if (do_res_stat(A_STR)) *ident = TRUE; if (do_res_stat(A_CON)) *ident = TRUE; if (player_clear_timed(p_ptr, TMD_POISONED, TRUE)) *ident = TRUE; return TRUE; } case EF_RING_ACID: { dam = 70 * (100 + boost) / 100; *ident = TRUE; fire_ball(GF_ACID, dir, dam, 2); player_inc_timed(p_ptr, TMD_OPP_ACID, randint1(20) + 20, TRUE, TRUE); return TRUE; } case EF_RING_FLAMES: { dam = 80 * (100 + boost) / 100; *ident = TRUE; fire_ball(GF_FIRE, dir, dam, 2); player_inc_timed(p_ptr, TMD_OPP_FIRE, randint1(20) + 20, TRUE, TRUE); return TRUE; } case EF_RING_ICE: { dam = 75 * (100 + boost) / 100; *ident = TRUE; fire_ball(GF_COLD, dir, dam, 2); player_inc_timed(p_ptr, TMD_OPP_COLD, randint1(20) + 20, TRUE, TRUE); return TRUE; } case EF_RING_LIGHTNING: { dam = 85 * (100 + boost) / 100; *ident = TRUE; fire_ball(GF_ELEC, dir, dam, 2); player_inc_timed(p_ptr, TMD_OPP_ELEC, randint1(20) + 20, TRUE, TRUE); return TRUE; } case EF_DRAGON_BLUE: { dam = 100 * (100 + boost) / 100; msgt(MSG_BR_ELEC, "You breathe lightning."); fire_ball(GF_ELEC, dir, dam, 2); return TRUE; } case EF_DRAGON_GREEN: { dam = 150 * (100 + boost) / 100; msgt(MSG_BR_GAS, "You breathe poison gas."); fire_ball(GF_POIS, dir, dam, 2); return TRUE; } case EF_DRAGON_RED: { dam = 200 * (100 + boost) / 100; msgt(MSG_BR_FIRE, "You breathe fire."); fire_ball(GF_FIRE, dir, dam, 2); return TRUE; } case EF_DRAGON_MULTIHUED: { static const struct { int msg_sound; const char *msg; int typ; } mh[] = { { MSG_BR_ELEC, "lightning", GF_ELEC }, { MSG_BR_FROST, "frost", GF_COLD }, { MSG_BR_ACID, "acid", GF_ACID }, { MSG_BR_GAS, "poison gas", GF_POIS }, { MSG_BR_FIRE, "fire", GF_FIRE } }; int chance = randint0(5); dam = 250 * (100 + boost) / 100; msgt(mh[chance].msg_sound, "You breathe %s.", mh[chance].msg); fire_ball(mh[chance].typ, dir, dam, 2); return TRUE; } case EF_DRAGON_BRONZE: { dam = 120 * (100 + boost) / 100; msgt(MSG_BR_CONF, "You breathe confusion."); fire_ball(GF_CONFU, dir, dam, 2); return TRUE; } case EF_DRAGON_GOLD: { dam = 130 * (100 + boost) / 100; msgt(MSG_BR_SOUND, "You breathe sound."); fire_ball(GF_SOUND, dir, dam, 2); return TRUE; } case EF_DRAGON_CHAOS: { dam = 220 * (100 + boost) / 100; chance = randint0(2); msgt((chance == 1 ? MSG_BR_CHAOS : MSG_BR_DISEN), "You breathe %s.", ((chance == 1 ? "chaos" : "disenchantment"))); fire_ball((chance == 1 ? GF_CHAOS : GF_DISEN), dir, dam, 2); return TRUE; } case EF_DRAGON_LAW: { dam = 230 * (100 + boost) / 100; chance = randint0(2); msgt((chance == 1 ? MSG_BR_SOUND : MSG_BR_SHARDS), "You breathe %s.", ((chance == 1 ? "sound" : "shards"))); fire_ball((chance == 1 ? GF_SOUND : GF_SHARD), dir, dam, 2); return TRUE; } case EF_DRAGON_BALANCE: { dam = 250 * (100 + boost) / 100; chance = randint0(4); msg("You breathe %s.", ((chance == 1) ? "chaos" : ((chance == 2) ? "disenchantment" : ((chance == 3) ? "sound" : "shards")))); fire_ball(((chance == 1) ? GF_CHAOS : ((chance == 2) ? GF_DISEN : ((chance == 3) ? GF_SOUND : GF_SHARD))), dir, dam, 2); return TRUE; } case EF_DRAGON_SHINING: { dam = 200 * (100 + boost) / 100; chance = randint0(2); msgt((chance == 0 ? MSG_BR_LIGHT : MSG_BR_DARK), "You breathe %s.", ((chance == 0 ? "light" : "darkness"))); fire_ball((chance == 0 ? GF_LIGHT : GF_DARK), dir, dam, 2); return TRUE; } case EF_DRAGON_POWER: { dam = 300 * (100 + boost) / 100; msgt(MSG_BR_ELEMENTS, "You breathe the elements."); fire_ball(GF_MISSILE, dir, dam, 2); return TRUE; } case EF_TRAP_DOOR: { msg("You fall through a trap door!"); if (check_state(p_ptr, OF_FEATHER, p_ptr->state.flags)) { msg("You float gently down to the next level."); } else { take_hit(p_ptr, damroll(2, 8), "a trap"); } wieldeds_notice_flag(p_ptr, OF_FEATHER); dungeon_change_level(p_ptr->depth + 1); return TRUE; } case EF_TRAP_PIT: { msg("You fall into a pit!"); if (check_state(p_ptr, OF_FEATHER, p_ptr->state.flags)) { msg("You float gently to the bottom of the pit."); } else { take_hit(p_ptr, damroll(2, 6), "a trap"); } wieldeds_notice_flag(p_ptr, OF_FEATHER); return TRUE; } case EF_TRAP_PIT_SPIKES: { msg("You fall into a spiked pit!"); if (check_state(p_ptr, OF_FEATHER, p_ptr->state.flags)) { msg("You float gently to the floor of the pit."); msg("You carefully avoid touching the spikes."); } else { int dam = damroll(2, 6); /* Extra spike damage */ if (one_in_(2)) { msg("You are impaled!"); dam *= 2; (void)player_inc_timed(p_ptr, TMD_CUT, randint1(dam), TRUE, TRUE); } take_hit(p_ptr, dam, "a trap"); } wieldeds_notice_flag(p_ptr, OF_FEATHER); return TRUE; } case EF_TRAP_PIT_POISON: { msg("You fall into a spiked pit!"); if (check_state(p_ptr, OF_FEATHER, p_ptr->state.flags)) { msg("You float gently to the floor of the pit."); msg("You carefully avoid touching the spikes."); } else { int dam = damroll(2, 6); /* Extra spike damage */ if (one_in_(2)) { msg("You are impaled on poisonous spikes!"); (void)player_inc_timed(p_ptr, TMD_CUT, randint1(dam * 2), TRUE, TRUE); (void)player_inc_timed(p_ptr, TMD_POISONED, randint1(dam * 4), TRUE, TRUE); } take_hit(p_ptr, dam, "a trap"); } wieldeds_notice_flag(p_ptr, OF_FEATHER); return TRUE; } case EF_TRAP_RUNE_SUMMON: { int i; int num = 2 + randint1(3); msgt(MSG_SUM_MONSTER, "You are enveloped in a cloud of smoke!"); /* Remove trap */ cave->info[py][px] &= ~(CAVE_MARK); cave_set_feat(cave, py, px, FEAT_FLOOR); for (i = 0; i < num; i++) (void)summon_specific(py, px, p_ptr->depth, 0, 1); return TRUE; } case EF_TRAP_RUNE_TELEPORT: { msg("You hit a teleport trap!"); teleport_player(100); return TRUE; } case EF_TRAP_SPOT_FIRE: { int dam; msg("You are enveloped in flames!"); dam = damroll(4, 6); dam = adjust_dam(p_ptr, GF_FIRE, dam, RANDOMISE, check_for_resist(p_ptr, GF_FIRE, p_ptr->state.flags, TRUE)); if (dam) { take_hit(p_ptr, dam, "a fire trap"); inven_damage(p_ptr, GF_FIRE, MIN(dam * 5, 300)); } return TRUE; } case EF_TRAP_SPOT_ACID: { int dam; msg("You are splashed with acid!"); dam = damroll(4, 6); dam = adjust_dam(p_ptr, GF_ACID, dam, RANDOMISE, check_for_resist(p_ptr, GF_ACID, p_ptr->state.flags, TRUE)); if (dam) { take_hit(p_ptr, dam, "an acid trap"); inven_damage(p_ptr, GF_ACID, MIN(dam * 5, 300)); } return TRUE; } case EF_TRAP_DART_SLOW: { if (trap_check_hit(125)) { msg("A small dart hits you!"); take_hit(p_ptr, damroll(1, 4), "a trap"); (void)player_inc_timed(p_ptr, TMD_SLOW, randint0(20) + 20, TRUE, FALSE); } else { msg("A small dart barely misses you."); } return TRUE; } case EF_TRAP_DART_LOSE_STR: { if (trap_check_hit(125)) { msg("A small dart hits you!"); take_hit(p_ptr, damroll(1, 4), "a trap"); (void)do_dec_stat(A_STR, FALSE); } else { msg("A small dart barely misses you."); } return TRUE; } case EF_TRAP_DART_LOSE_DEX: { if (trap_check_hit(125)) { msg("A small dart hits you!"); take_hit(p_ptr, damroll(1, 4), "a trap"); (void)do_dec_stat(A_DEX, FALSE); } else { msg("A small dart barely misses you."); } return TRUE; } case EF_TRAP_DART_LOSE_CON: { if (trap_check_hit(125)) { msg("A small dart hits you!"); take_hit(p_ptr, damroll(1, 4), "a trap"); (void)do_dec_stat(A_CON, FALSE); } else { msg("A small dart barely misses you."); } return TRUE; } case EF_TRAP_GAS_BLIND: { msg("You are surrounded by a black gas!"); (void)player_inc_timed(p_ptr, TMD_BLIND, randint0(50) + 25, TRUE, TRUE); return TRUE; } case EF_TRAP_GAS_CONFUSE: { msg("You are surrounded by a gas of scintillating colors!"); (void)player_inc_timed(p_ptr, TMD_CONFUSED, randint0(20) + 10, TRUE, TRUE); return TRUE; } case EF_TRAP_GAS_POISON: { msg("You are surrounded by a pungent green gas!"); (void)player_inc_timed(p_ptr, TMD_POISONED, randint0(20) + 10, TRUE, TRUE); return TRUE; } case EF_TRAP_GAS_SLEEP: { msg("You are surrounded by a strange white mist!"); (void)player_inc_timed(p_ptr, TMD_PARALYZED, randint0(10) + 5, TRUE, TRUE); return TRUE; } case EF_XXX: case EF_MAX: break; } /* Not used */ msg("Effect not handled."); return FALSE; }
/* * Set a timed event (except timed resists, cutting and stunning). */ bool player_set_timed(struct player *p, int idx, int v, bool notify) { timed_effect *effect; /* Hack -- Force good values */ v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; if ((idx < 0) || (idx > TMD_MAX)) return FALSE; /* No change */ if (p->timed[idx] == v) return FALSE; /* Hack -- call other functions */ if (idx == TMD_STUN) return set_stun(p, v); else if (idx == TMD_CUT) return set_cut(p, v); /* Don't mention effects which already match the player state. */ if (idx == TMD_OPP_ACID && check_state(p, OF_IM_ACID, p->state.flags)) notify = FALSE; else if (idx == TMD_OPP_ELEC && check_state(p, OF_IM_ELEC, p->state.flags)) notify = FALSE; else if (idx == TMD_OPP_FIRE && check_state(p, OF_IM_FIRE, p->state.flags)) notify = FALSE; else if (idx == TMD_OPP_COLD && check_state(p, OF_IM_COLD, p->state.flags)) notify = FALSE; else if (idx == TMD_OPP_CONF && of_has(p->state.flags, OF_RES_CONFU)) notify = FALSE; /* Find the effect */ effect = &effects[idx]; /* Turning off, always mention */ if (v == 0) { msgt(MSG_RECOVER, "%s", effect->on_end); notify = TRUE; } /* Turning on, always mention */ else if (p->timed[idx] == 0) { msgt(effect->msg, "%s", effect->on_begin); notify = TRUE; } else if (notify) { /* Decrementing */ if (p->timed[idx] > v && effect->on_decrease) msgt(effect->msg, "%s", effect->on_decrease); /* Incrementing */ else if (v > p->timed[idx] && effect->on_increase) msgt(effect->msg, "%s", effect->on_increase); } /* Use the value */ p->timed[idx] = v; /* Sort out the sprint effect */ if (idx == TMD_SPRINT && v == 0) player_inc_timed(p, TMD_SLOW, 100, TRUE, FALSE); /* Nothing to notice */ if (!notify) return FALSE; /* Disturb */ disturb(p, 0, 0); /* Update the visuals, as appropriate. */ p->update |= effect->flag_update; p->redraw |= (PR_STATUS | effect->flag_redraw); /* Handle stuff */ handle_stuff(p); /* Result */ return TRUE; }
static void project_player_handler_POIS(project_player_handler_context_t *context) { if (!player_inc_timed(player, TMD_POISONED, 10 + randint1(context->dam), true, true)) msg("You resist the effect!"); }
/** * Handle things that need updating once every 10 game turns */ void process_world(struct chunk *c) { int i, y, x; /* Compact the monster list if we're approaching the limit */ if (cave_monster_count(cave) + 32 > z_info->level_monster_max) compact_monsters(64); /* Too many holes in the monster list - compress */ if (cave_monster_count(cave) + 32 < cave_monster_max(cave)) compact_monsters(0); /*** Check the Time ***/ /* Play an ambient sound at regular intervals. */ if (!(turn % ((10L * z_info->day_length) / 4))) play_ambient_sound(); /*** Handle stores and sunshine ***/ if (!player->depth) { /* Daybreak/Nighfall in town */ if (!(turn % ((10L * z_info->day_length) / 2))) { bool dawn; /* Check for dawn */ dawn = (!(turn % (10L * z_info->day_length))); /* Day breaks */ if (dawn) msg("The sun has risen."); /* Night falls */ else msg("The sun has fallen."); /* Illuminate */ cave_illuminate(c, dawn); } } else { /* Update the stores once a day (while in the dungeon). The changes are not actually made until return to town, to avoid giving details away in the knowledge menu. */ if (!(turn % (10L * z_info->store_turns))) daycount++; } /* Check for creature generation */ if (one_in_(z_info->alloc_monster_chance)) (void)pick_and_place_distant_monster(cave, player, z_info->max_sight + 5, true, player->depth); /*** Damage over Time ***/ /* Take damage from poison */ if (player->timed[TMD_POISONED]) take_hit(player, 1, "poison"); /* Take damage from cuts */ if (player->timed[TMD_CUT]) { /* Mortal wound or Deep Gash */ if (player->timed[TMD_CUT] > TMD_CUT_SEVERE) i = 3; /* Severe cut */ else if (player->timed[TMD_CUT] > TMD_CUT_NASTY) i = 2; /* Other cuts */ else i = 1; /* Take damage */ take_hit(player, i, "a fatal wound"); } /*** Check the Food, and Regenerate ***/ /* Digest normally */ if (!(turn % 100)) { /* Basic digestion rate based on speed */ i = turn_energy(player->state.speed) * 2; /* Regeneration takes more food */ if (player_of_has(player, OF_REGEN)) i += 30; /* Slow digestion takes less food */ if (player_of_has(player, OF_SLOW_DIGEST)) i /= 5; /* Minimal digestion */ if (i < 1) i = 1; /* Digest some food */ player_set_food(player, player->food - i); } /* Getting Faint */ if (player->food < PY_FOOD_FAINT) { /* Faint occasionally */ if (!player->timed[TMD_PARALYZED] && one_in_(10)) { /* Message */ msg("You faint from the lack of food."); disturb(player, 1); /* Faint (bypass free action) */ (void)player_inc_timed(player, TMD_PARALYZED, 1 + randint0(5), true, false); } } /* Starve to death (slowly) */ if (player->food < PY_FOOD_STARVE) { /* Calculate damage */ i = (PY_FOOD_STARVE - player->food) / 10; /* Take damage */ take_hit(player, i, "starvation"); } /* Regenerate Hit Points if needed */ if (player->chp < player->mhp) player_regen_hp(player); /* Regenerate mana if needed */ if (player->csp < player->msp) player_regen_mana(player); /* Timeout various things */ decrease_timeouts(); /* Process light */ player_update_light(player); /*** Process Inventory ***/ /* Handle experience draining */ if (player_of_has(player, OF_DRAIN_EXP)) { if ((player->exp > 0) && one_in_(10)) { s32b d = damroll(10, 6) + (player->exp / 100) * z_info->life_drain_percent; player_exp_lose(player, d / 10, false); } equip_learn_flag(player, OF_DRAIN_EXP); } /* Recharge activatable objects and rods */ recharge_objects(); /* Notice things after time */ if (!(turn % 100)) equip_learn_after_time(player); /* Decrease trap timeouts */ for (y = 0; y < cave->height; y++) { for (x = 0; x < cave->width; x++) { struct trap *trap = cave->squares[y][x].trap; while (trap) { if (trap->timeout) { trap->timeout--; if (!trap->timeout) square_light_spot(cave, y, x); } trap = trap->next; } } } /*** Involuntary Movement ***/ /* Delayed Word-of-Recall */ if (player->word_recall) { /* Count down towards recall */ player->word_recall--; /* Activate the recall */ if (!player->word_recall) { /* Disturbing! */ disturb(player, 0); /* Determine the level */ if (player->depth) { msgt(MSG_TPLEVEL, "You feel yourself yanked upwards!"); dungeon_change_level(player, 0); } else { msgt(MSG_TPLEVEL, "You feel yourself yanked downwards!"); /* Force descent to a lower level if allowed */ if (OPT(player, birth_force_descend) && player->max_depth < z_info->max_depth - 1 && !is_quest(player->max_depth)) { player->max_depth = dungeon_get_next_level(player->max_depth, 1); } /* New depth - back to max depth or 1, whichever is deeper */ dungeon_change_level(player, player->max_depth < 1 ? 1: player->max_depth); } } } /* Delayed Deep Descent */ if (player->deep_descent) { /* Count down towards recall */ player->deep_descent--; /* Activate the recall */ if (player->deep_descent == 0) { int target_increment; int target_depth = player->max_depth; /* Calculate target depth */ target_increment = (4 / z_info->stair_skip) + 1; target_depth = dungeon_get_next_level(player->max_depth, target_increment); disturb(player, 0); /* Determine the level */ if (target_depth > player->depth) { msgt(MSG_TPLEVEL, "The floor opens beneath you!"); dungeon_change_level(player, target_depth); } else { /* Otherwise do something disastrous */ msgt(MSG_TPLEVEL, "You are thrown back in an explosion!"); effect_simple(EF_DESTRUCTION, "0", 0, 5, 0, NULL); } } } }
static void project_player_handler_FORCE(project_player_handler_context_t *context) { /* Stun */ (void)player_inc_timed(player, TMD_STUN, randint1(20), TRUE, TRUE); }
/* * Chests have traps too. * * Exploding chest destroys contents (and traps). * Note that the chest itself is never destroyed. */ static void chest_trap(int y, int x, s16b o_idx) { int i, trap; object_type *o_ptr = object_byid(o_idx); /* Ignore disarmed chests */ if (o_ptr->pval[DEFAULT_PVAL] <= 0) return; /* Obtain the traps */ trap = chest_traps[o_ptr->pval[DEFAULT_PVAL]]; /* Lose strength */ if (trap & (CHEST_LOSE_STR)) { msg("A small needle has pricked you!"); take_hit(p_ptr, damroll(1, 4), "a poison needle"); (void)do_dec_stat(A_STR, FALSE); } /* Lose constitution */ if (trap & (CHEST_LOSE_CON)) { msg("A small needle has pricked you!"); take_hit(p_ptr, damroll(1, 4), "a poison needle"); (void)do_dec_stat(A_CON, FALSE); } /* Poison */ if (trap & (CHEST_POISON)) { msg("A puff of green gas surrounds you!"); (void)player_inc_timed(p_ptr, TMD_POISONED, 10 + randint1(20), TRUE, TRUE); } /* Paralyze */ if (trap & (CHEST_PARALYZE)) { msg("A puff of yellow gas surrounds you!"); (void)player_inc_timed(p_ptr, TMD_PARALYZED, 10 + randint1(20), TRUE, TRUE); } /* Summon monsters */ if (trap & (CHEST_SUMMON)) { int num = 2 + randint1(3); msg("You are enveloped in a cloud of smoke!"); sound(MSG_SUM_MONSTER); for (i = 0; i < num; i++) { (void)summon_specific(y, x, p_ptr->depth, 0, 1); } } /* Explode */ if (trap & (CHEST_EXPLODE)) { msg("There is a sudden explosion!"); msg("Everything inside the chest is destroyed!"); o_ptr->pval[DEFAULT_PVAL] = 0; take_hit(p_ptr, damroll(5, 8), "an exploding chest"); } }
/* * Perform the basic "bash" command * * Assume there is no monster blocking the destination * * Returns TRUE if repeated commands may continue */ static bool do_cmd_bash_aux(int y, int x) { int bash, temp; bool more = FALSE; /* Verify legality */ if (!do_cmd_bash_test(y, x)) return (FALSE); /* Message */ msg("You smash into the door!"); /* Hack -- Bash power based on strength */ /* (Ranges from 3 to 20 to 100 to 200) */ bash = adj_str_blow[p_ptr->state.stat_ind[A_STR]]; /* Extract door power */ temp = ((cave->feat[y][x] - FEAT_DOOR_HEAD) & 0x07); /* Compare bash power to door power */ temp = (bash - (temp * 10)); /* Hack -- always have a chance */ if (temp < 1) temp = 1; /* Hack -- attempt to bash down the door */ if (randint0(100) < temp) { /* Break down the door */ if (randint0(100) < 50) { cave_set_feat(cave, y, x, FEAT_BROKEN); } /* Open the door */ else { cave_set_feat(cave, y, x, FEAT_OPEN); } msgt(MSG_OPENDOOR, "The door crashes open!"); /* Update the visuals */ p_ptr->update |= (PU_UPDATE_VIEW | PU_MONSTERS); } /* Saving throw against stun */ else if (randint0(100) < adj_dex_safe[p_ptr->state.stat_ind[A_DEX]] + p_ptr->lev) { msg("The door holds firm."); /* Allow repeated bashing */ more = TRUE; } /* Low dexterity has bad consequences */ else { msg("You are off-balance."); /* Lose balance ala stun */ (void)player_inc_timed(p_ptr, TMD_STUN, 2 + randint0(2), TRUE, FALSE); } /* Result */ return more; }