static void _seal_of_mirror_fn(int y, int x) { int dam = spell_power(p_ptr->lev*4 + 100); if (project_m(0, 0, y, x, dam, GF_GENOCIDE, PROJECT_GRID|PROJECT_ITEM|PROJECT_KILL|PROJECT_JUMP,TRUE)) { if(!cave[y][x].m_idx) remove_mirror(y,x); } }
/* * Apply a "project()" directly to all monsters in view of a certain spot. * * Note that affected monsters are NOT auto-tracked by this usage. * * We are able to check LOS from either the character (in which case we * use line of fire for speed and accuracy), or from any given grid. * * To avoid misbehavior when monster deaths have side-effects, * this is done in two passes. -- JDL */ bool project_los(int y0, int x0, int dam, int typ) { int i, d, x, y; u32b flg = PROJECT_JUMP | PROJECT_KILL | PROJECT_HIDE; bool obvious = FALSE; int who; /* Determine whether we are using LOF or LOS */ bool line_of_fire = FALSE; if ((y0 == p_ptr->py) && (x0 == p_ptr->px)) { line_of_fire = TRUE; who = SOURCE_PLAYER; } else if (cave_monster_trap_bold(y0, x0)) who = SOURCE_TRAP; else if (cave_player_trap_bold(y0, x0)) who = SOURCE_EFFECT; else who = SOURCE_OTHER; /* Mark monsters in LOS */ for (i = 1; i < mon_max; i++) { monster_type *m_ptr = &mon_list[i]; /* Paranoia -- Skip dead monsters */ if (!m_ptr->r_idx) continue; /* Location */ y = m_ptr->fy; x = m_ptr->fx; /* Apply character-centered test */ if (line_of_fire) { /* Require line of fire */ if (!player_can_fire_bold(y, x)) continue; } /* Apply generic grid test */ else { /* Get distance between source and monster */ d = distance(y0, x0, y, x); /* LOS extends only to max sight range */ if (d > MAX_RANGE) continue; /* Check LOS if not at grid or adjacent */ if (d > 1) { /* Ignore if not in LOS */ if (!los(y0, x0, y, x)) continue; } } /* Mark the monster */ m_ptr->mflag |= (MFLAG_TEMP); } /* Affect all (nearby) monsters */ for (i = 1; i < mon_max; i++) { monster_type *m_ptr = &mon_list[i]; /* Skip unmarked monsters */ if (!(m_ptr->mflag & (MFLAG_TEMP))) continue; /* Remove mark */ m_ptr->mflag &= ~(MFLAG_TEMP); /* Jump directly to the monster */ if (project_m(who, m_ptr->fy, m_ptr->fx, dam, typ, flg)) { obvious = TRUE; } } /* Result */ return (obvious); }
/* * Handle monster hitting a real trap. */ void mon_hit_trap(int m_idx, int y, int x) { feature_type *f_ptr; monster_type *m_ptr = &m_list[m_idx]; monster_race *r_ptr = &r_info[m_ptr->r_idx]; int feat = cave_feat[y][x]; bool fear; /* Option */ if (!variant_hit_traps) return; /* Hack --- don't activate unknown invisible traps */ if (cave_feat[y][x] == FEAT_INVIS) return; /* Get feature */ f_ptr = &f_info[cave_feat[y][x]]; /* Hack --- trapped doors */ /* XXX XXX Dangerous */ while (!(f_ptr->spell) && !(f_ptr->blow.method) && (f_ptr->flags1 & (FF1_TRAP))) { pick_trap(y,x); /* Error */ if (cave_feat[y][x] == feat) break; feat = cave_feat[y][x]; /* Get feature */ f_ptr = &f_info[feat]; } /* Use covered or bridged if necessary */ if ((f_ptr->flags2 & (FF2_COVERED)) || (f_ptr->flags2 & (FF2_BRIDGED))) { f_ptr = &f_info[f_ptr->mimic]; } /* Hack -- monster falls onto trap */ if ((m_ptr->fy!=y)|| (m_ptr->fx !=x)) { /* Move monster */ monster_swap(m_ptr->fy, m_ptr->fx, y, x); } /* Apply the object */ if ((cave_o_idx[y][x]) && (f_ptr->flags1 & (FF1_HIT_TRAP))) { object_type *o_ptr = &o_list[cave_o_idx[y][x]]; char o_name[80]; int power = 0; switch (o_ptr->tval) { case TV_BOW: { object_type *j_ptr; u32b f1,f2,f3; int i, shots = 1; /* Get bow */ j_ptr = o_ptr; /* Get bow flags */ object_flags(o_ptr,&f1,&f2,&f3); /* Apply extra shots */ if (f1 & (TR1_SHOTS)) shots += j_ptr->pval; /* Test for hit */ for (i = 0; i < shots; i++) { if (j_ptr->next_o_idx) { int ammo = j_ptr->next_o_idx; object_type *i_ptr; object_type object_type_body; /* Use ammo instead of bow */ o_ptr = &o_list[ammo]; /* Describe ammo */ object_desc(o_name, sizeof(o_name), o_ptr, TRUE, 0); if ((ammo) && (test_hit_fire((j_ptr->to_h + o_ptr->to_h)* BTH_PLUS_ADJ + f_ptr->power, r_ptr->ac * (r_ptr->flags2 & (RF2_ARMOR) ? 2 : 1), TRUE))) { int k, mult; switch (j_ptr->sval) { case SV_SLING: case SV_SHORT_BOW: mult = 2; break; case SV_LONG_BOW: case SV_LIGHT_XBOW: mult = 3; break; case SV_HEAVY_XBOW: mult = 4; break; default: mult = 1; break; } /* Apply extra might */ if (f1 & (TR1_MIGHT)) mult += j_ptr->pval; k = damroll(o_ptr->dd, o_ptr->ds); k *= mult; k = tot_dam_aux(o_ptr, k, m_ptr); k = critical_shot(o_ptr->weight, o_ptr->to_h + j_ptr->to_h, k); k += o_ptr->to_d + j_ptr->to_d; /* No negative damage */ if (k < 0) k = 0; /* Trap description */ msg_format("%^s hits you.",o_name); /* Damage, check for fear and death */ (void)mon_take_hit(cave_m_idx[y][x], k, &fear, NULL); } else { /* Trap description */ msg_format("%^s narrowly misses you.",o_name); } /* Get local object */ i_ptr = &object_type_body; /* Obtain a local object */ object_copy(i_ptr, o_ptr); /* Modify quantity */ i_ptr->number = 1; /* Drop nearby - some chance of breakage */ drop_near(i_ptr,y,x,breakage_chance(i_ptr)); /* Decrease the item */ floor_item_increase(ammo, -1); floor_item_optimize(ammo); break; } else { /* Disarm */ cave_alter_feat(y,x,FS_DISARM); } } } case TV_SHOT: case TV_ARROW: case TV_BOLT: case TV_HAFTED: case TV_SWORD: case TV_POLEARM: { object_type *i_ptr; object_type object_type_body; /* Describe ammo */ object_desc(o_name, sizeof(o_name), o_ptr, TRUE, 0); /* Test for hit */ if (test_hit_norm(o_ptr->to_h * BTH_PLUS_ADJ + f_ptr->power, r_ptr->ac, TRUE)) { int k; k = damroll(o_ptr->dd, o_ptr->ds); k = tot_dam_aux(o_ptr, k, m_ptr); k = critical_norm(o_ptr->weight, o_ptr->to_h, k); k += o_ptr->to_d; /* Armour reduces total damage */ k -= (k * ((p_ptr->ac < 150) ? p_ptr->ac : 150) / 250); /* No negative damage */ if (k < 0) k = 0; /* Trap description */ msg_format("%^s hits you.",o_name); /* Damage, check for fear and death */ (void)mon_take_hit(cave_m_idx[y][x], k, &fear, NULL); } else { /* Trap description */ msg_format("%^s narrowly misses you.",o_name); } /* Get local object */ i_ptr = &object_type_body; /* Obtain a local object */ object_copy(i_ptr, o_ptr); /* Modify quantity */ i_ptr->number = 1; /* Drop nearby - some chance of breakage */ drop_near(i_ptr,y,x,breakage_chance(i_ptr)); /* Decrease the item */ floor_item_increase(cave_o_idx[y][x], -1); floor_item_optimize(cave_o_idx[y][x]); /* Disarm if runs out */ if (!cave_o_idx[y][x]) cave_alter_feat(y,x,FS_DISARM); break; } case TV_WAND: case TV_STAFF: { if (o_ptr->pval > 0) { /* Get item effect */ get_spell(&power, "use", o_ptr, FALSE); /* XXX Hack -- new unstacking code */ o_ptr->stackc++; /* No spare charges */ if (o_ptr->stackc >= o_ptr->number) { /* Use a charge off the stack */ o_ptr->pval--; /* Reset the stack count */ o_ptr->stackc = 0; } /* XXX Hack -- unstack if necessary */ if ((o_ptr->number > 1) && ((!variant_pval_stacks) || ((!object_known_p(o_ptr) && (o_ptr->pval == 2) && (o_ptr->stackc > 1)) || (!object_known_p(o_ptr) && (rand_int(o_ptr->number) <= o_ptr->stackc) && (o_ptr->stackc != 1) && (o_ptr->pval > 2))))) { object_type *i_ptr; object_type object_type_body; /* Get local object */ i_ptr = &object_type_body; /* Obtain a local object */ object_copy(i_ptr, o_ptr); /* Modify quantity */ i_ptr->number = 1; /* Reset stack counter */ i_ptr->stackc = 0; /* Unstack the used item */ o_ptr->number--; /* Reduce the charges on the new item */ if (o_ptr->stackc > 1) { i_ptr->pval-=2; o_ptr->stackc--; } else if (!o_ptr->stackc) { i_ptr->pval--; o_ptr->pval++; o_ptr->stackc = o_ptr->number-1; } (void)floor_carry(y,x,i_ptr); } } else { /* Disarm if runs out */ cave_alter_feat(y,x,FS_DISARM); } break; } case TV_ROD: case TV_DRAG_ARMOR: { if (!((o_ptr->timeout) && ((!o_ptr->stackc) || (o_ptr->stackc >= o_ptr->number)))) { int tmpval; /* Store pval */ tmpval = o_ptr->timeout; /* Time rod out */ o_ptr->timeout = o_ptr->pval; /* Get item effect */ get_spell(&power, "use", o_ptr, FALSE); /* Has a power */ /* Hack -- check if we are stacking rods */ if ((o_ptr->timeout > 0) && (!(tmpval) || stack_force_times)) { /* Hack -- one more rod charging */ if (o_ptr->timeout) o_ptr->stackc++; /* Reset stack count */ if (o_ptr->stackc == o_ptr->number) o_ptr->stackc = 0; /* Hack -- always use maximum timeout */ if (tmpval > o_ptr->timeout) o_ptr->timeout = tmpval; } /* XXX Hack -- unstack if necessary */ if ((o_ptr->number > 1) && (o_ptr->timeout > 0)) { object_type *i_ptr; object_type object_type_body; /* Get local object */ i_ptr = &object_type_body; /* Obtain a local object */ object_copy(i_ptr, o_ptr); /* Modify quantity */ i_ptr->number = 1; /* Clear stack counter */ i_ptr->stackc = 0; /* Restore "charge" */ o_ptr->timeout = tmpval; /* Unstack the used item */ o_ptr->number--; /* Reset the stack if required */ if (o_ptr->stackc == o_ptr->number) o_ptr->stackc = 0; (void)floor_carry(y,x,i_ptr); } } break; } case TV_POTION: case TV_SCROLL: case TV_FLASK: case TV_FOOD: { /* Hack -- boring food */ if ((o_ptr->tval == TV_FOOD) && (o_ptr->sval >= SV_FOOD_MIN_FOOD)) { /* Disarm */ cave_alter_feat(y,x,FS_DISARM); } else { /* Get item effect */ get_spell(&power, "use", o_ptr, FALSE); /* Decrease the item */ floor_item_increase(cave_o_idx[y][x], -1); floor_item_optimize(cave_o_idx[y][x]); /* Disarm if runs out */ if (!cave_o_idx[y][x]) cave_alter_feat(y,x,FS_DISARM); } break; } case TV_RUNESTONE: { u32b runes = p_ptr->cur_runes; int num = 0; s16b book[26]; /* Hack -- use current rune */ p_ptr->cur_runes = (2 << (o_ptr->sval-1)); /* Fill the book with spells */ fill_book(o_ptr,book,&num); /* Unhack */ p_ptr->cur_runes = runes; /* Get a power */ power = book[rand_int(num)]; /* Decrease the item */ floor_item_increase(cave_o_idx[y][x], -1); floor_item_optimize(cave_o_idx[y][x]); /* Disarm if runs out */ if (!cave_o_idx[y][x]) cave_alter_feat(y,x,FS_DISARM); break; } default: { /* Disarm */ cave_alter_feat(y,x,FS_DISARM); break; } } /* Has a power */ if (power > 0) { spell_type *s_ptr = &s_info[power]; int ap_cnt; /* Object is used */ if (k_info[o_ptr->k_idx].used < MAX_SHORT) k_info[o_ptr->k_idx].used++; /* Scan through all four blows */ for (ap_cnt = 0; ap_cnt < 4; ap_cnt++) { int damage = 0; /* Extract the attack infomation */ int effect = s_ptr->blow[ap_cnt].effect; int method = s_ptr->blow[ap_cnt].method; int d_dice = s_ptr->blow[ap_cnt].d_dice; int d_side = s_ptr->blow[ap_cnt].d_side; int d_plus = s_ptr->blow[ap_cnt].d_plus; /* Hack -- no more attacks */ if (!method) break; /* Mega hack -- dispel evil/undead objects */ if (!d_side) { d_plus += 25 * d_dice; } /* Roll out the damage */ if ((d_dice) && (d_side)) { damage = damroll(d_dice, d_side) + d_plus; } else { damage = d_plus; } (void)project_m(0,0,y,x,damage, effect); (void)project_f(0,0,y,x,damage, effect); } } } /* Regular traps */ else { if (f_ptr->spell) { make_attack_spell_aux(0,y,x,f_ptr->spell); } else if (f_ptr->blow.method) { int damage = damroll(f_ptr->blow.d_side,f_ptr->blow.d_dice); /* Apply the blow */ project_m(0, 0, y, x, damage, f_ptr->blow.effect); } /* Get feature */ f_ptr = &f_info[cave_feat[p_ptr->py][p_ptr->px]]; if (f_ptr->flags1 & (FF1_HIT_TRAP)) { /* Modify the location hit by the trap */ cave_alter_feat(y,x,FS_HIT_TRAP); } else if (f_ptr->flags1 & (FF1_SECRET)) { /* Discover */ cave_alter_feat(y,x,FS_SECRET); } } }