#include "object-enchant/special-object-flags.h"
#include "object-enchant/tr-types.h"
#include "object-enchant/trc-types.h"
+#include "object-hook/hook-enchant.h"
+#include "object-hook/hook-expendable.h"
+#include "object-hook/hook-magic.h"
+#include "object-hook/hook-perception.h"
+#include "object-hook/hook-weapon.h"
+#include "object/item-tester-hooker.h"
#include "object/item-use-flags.h"
#include "object/object-flavor.h"
#include "object/object-generator.h"
-#include "object/object-hook.h"
#include "object/object-info.h"
#include "object/object-kind.h"
#include "object/object-mark-types.h"
#include "perception/identification.h"
#include "perception/object-perception.h"
#include "player/avatar.h"
-#include "player/bad-status-setter.h"
+#include "player/digestion-processor.h"
#include "player/player-class.h"
#include "player/player-damage.h"
#include "player/player-effects.h"
#include "spell/spells-execution.h"
#include "spell/spells-summon.h"
#include "spell/technic-info-table.h"
+#include "status/bad-status-setter.h"
#include "term/screen-processor.h"
#include "term/term-color-types.h"
#include "util/bit-flags-calculator.h"
#include "view/display-messages.h"
#include "world/world.h"
-// todo コピペ感が強くなったので関数化
-static bool update_player(player_type *caster_ptr);
-static bool redraw_player(player_type *caster_ptr);
-
/*!
* @brief プレイヤーの装備劣化処理 /
* Apply disenchantment to the player's stuff
if (!o_ptr->k_idx)
return FALSE;
- if (!object_is_weapon_armour_ammo(o_ptr))
+ if (!object_is_weapon_armour_ammo(target_ptr, o_ptr))
return FALSE;
if ((o_ptr->to_h <= 0) && (o_ptr->to_d <= 0) && (o_ptr->to_a <= 0) && (o_ptr->pval <= 1)) {
}
/*!
- * @brief 虚無招来によるフロア中の全壁除去処理 /
- * Vanish all walls in this floor
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @params caster_ptr 術者の参照ポインタ
- * @return 実際に処理が反映された場合TRUE
- */
-bool vanish_dungeon(player_type *caster_ptr)
-{
- bool is_special_floor = caster_ptr->current_floor_ptr->inside_quest && is_fixed_quest_idx(caster_ptr->current_floor_ptr->inside_quest);
- is_special_floor |= !caster_ptr->current_floor_ptr->dun_level;
- if (is_special_floor)
- return FALSE;
-
- grid_type *g_ptr;
- feature_type *f_ptr;
- monster_type *m_ptr;
- GAME_TEXT m_name[MAX_NLEN];
- for (POSITION y = 1; y < caster_ptr->current_floor_ptr->height - 1; y++) {
- for (POSITION x = 1; x < caster_ptr->current_floor_ptr->width - 1; x++) {
- g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
-
- f_ptr = &f_info[g_ptr->feat];
- g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
- m_ptr = &caster_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
- if (g_ptr->m_idx && monster_csleep_remaining(m_ptr)) {
- (void)set_monster_csleep(caster_ptr, g_ptr->m_idx, 0);
- if (m_ptr->ml) {
- monster_desc(caster_ptr, m_name, m_ptr, 0);
- msg_format(_("%^sが目を覚ました。", "%^s wakes up."), m_name);
- }
- }
-
- if (have_flag(f_ptr->flags, FF_HURT_DISI))
- cave_alter_feat(caster_ptr, y, x, FF_HURT_DISI);
- }
- }
-
- for (POSITION x = 0; x < caster_ptr->current_floor_ptr->width; x++) {
- g_ptr = &caster_ptr->current_floor_ptr->grid_array[0][x];
- f_ptr = &f_info[g_ptr->mimic];
- g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
-
- if (g_ptr->mimic && have_flag(f_ptr->flags, FF_HURT_DISI)) {
- g_ptr->mimic = feat_state(caster_ptr, g_ptr->mimic, FF_HURT_DISI);
- if (!have_flag(f_info[g_ptr->mimic].flags, FF_REMEMBER))
- g_ptr->info &= ~(CAVE_MARK);
- }
-
- g_ptr = &caster_ptr->current_floor_ptr->grid_array[caster_ptr->current_floor_ptr->height - 1][x];
- f_ptr = &f_info[g_ptr->mimic];
- g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
-
- if (g_ptr->mimic && have_flag(f_ptr->flags, FF_HURT_DISI)) {
- g_ptr->mimic = feat_state(caster_ptr, g_ptr->mimic, FF_HURT_DISI);
- if (!have_flag(f_info[g_ptr->mimic].flags, FF_REMEMBER))
- g_ptr->info &= ~(CAVE_MARK);
- }
- }
-
- /* Special boundary walls -- Left and right */
- for (POSITION y = 1; y < (caster_ptr->current_floor_ptr->height - 1); y++) {
- g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][0];
- f_ptr = &f_info[g_ptr->mimic];
- g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
-
- if (g_ptr->mimic && have_flag(f_ptr->flags, FF_HURT_DISI)) {
- g_ptr->mimic = feat_state(caster_ptr, g_ptr->mimic, FF_HURT_DISI);
- if (!have_flag(f_info[g_ptr->mimic].flags, FF_REMEMBER))
- g_ptr->info &= ~(CAVE_MARK);
- }
-
- g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][caster_ptr->current_floor_ptr->width - 1];
- f_ptr = &f_info[g_ptr->mimic];
- g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
-
- if (g_ptr->mimic && have_flag(f_ptr->flags, FF_HURT_DISI)) {
- g_ptr->mimic = feat_state(caster_ptr, g_ptr->mimic, FF_HURT_DISI);
- if (!have_flag(f_info[g_ptr->mimic].flags, FF_REMEMBER))
- g_ptr->info &= ~(CAVE_MARK);
- }
- }
-
- caster_ptr->update |= (PU_UN_VIEW | PU_UN_LITE | PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE | PU_MONSTERS);
- caster_ptr->redraw |= (PR_MAP);
- caster_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
- return TRUE;
-}
-
-/*!
- * @brief 虚無招来処理 /
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @return なし
- * @details
- * Sorry, it becomes not (void)...
- */
-void call_the_void(player_type *caster_ptr)
-{
- grid_type *g_ptr;
- bool do_call = TRUE;
- for (int i = 0; i < 9; i++) {
- g_ptr = &caster_ptr->current_floor_ptr->grid_array[caster_ptr->y + ddy_ddd[i]][caster_ptr->x + ddx_ddd[i]];
-
- if (!cave_have_flag_grid(g_ptr, FF_PROJECT)) {
- if (!g_ptr->mimic || !have_flag(f_info[g_ptr->mimic].flags, FF_PROJECT) || !permanent_wall(&f_info[g_ptr->feat])) {
- do_call = FALSE;
- break;
- }
- }
- }
-
- if (do_call) {
- for (int i = 1; i < 10; i++) {
- if (i - 5)
- fire_ball(caster_ptr, GF_ROCKET, i, 175, 2);
- }
-
- for (int i = 1; i < 10; i++) {
- if (i - 5)
- fire_ball(caster_ptr, GF_MANA, i, 175, 3);
- }
-
- for (int i = 1; i < 10; i++) {
- if (i - 5)
- fire_ball(caster_ptr, GF_NUKE, i, 175, 4);
- }
-
- return;
- }
-
- bool is_special_fllor = caster_ptr->current_floor_ptr->inside_quest && is_fixed_quest_idx(caster_ptr->current_floor_ptr->inside_quest);
- is_special_fllor |= !caster_ptr->current_floor_ptr->dun_level;
- if (is_special_fllor) {
- msg_print(_("地面が揺れた。", "The ground trembles."));
- return;
- }
-
-#ifdef JP
- msg_format("あなたは%sを壁に近すぎる場所で唱えてしまった!", ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "祈り" : "呪文"));
-#else
- msg_format("You %s the %s too close to a wall!", ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),
- ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "prayer" : "spell"));
-#endif
- msg_print(_("大きな爆発音があった!", "There is a loud explosion!"));
-
- if (one_in_(666)) {
- if (!vanish_dungeon(caster_ptr))
- msg_print(_("ダンジョンは一瞬静まり返った。", "The dungeon becomes quiet for a moment."));
- take_hit(caster_ptr, DAMAGE_NOESCAPE, 100 + randint1(150), _("自殺的な虚無招来", "a suicidal Call the Void"), -1);
- return;
- }
-
- if (destroy_area(caster_ptr, caster_ptr->y, caster_ptr->x, 15 + caster_ptr->lev + randint0(11), FALSE))
- msg_print(_("ダンジョンが崩壊した...", "The dungeon collapses..."));
- else
- msg_print(_("ダンジョンは大きく揺れた。", "The dungeon trembles."));
- take_hit(caster_ptr, DAMAGE_NOESCAPE, 100 + randint1(150), _("自殺的な虚無招来", "a suicidal Call the Void"), -1);
-}
-
-/*!
* @brief アイテム引き寄せ処理 /
* Fetch an item (teleport it right underneath the caster)
* @param caster_ptr プレーヤーへの参照ポインタ
tx = target_col;
ty = target_row;
- if (distance(caster_ptr->y, caster_ptr->x, ty, tx) > MAX_RANGE) {
+ if (distance(caster_ptr->y, caster_ptr->x, ty, tx) > get_max_range(caster_ptr)) {
msg_print(_("そんなに遠くにある物は取れません!", "You can't fetch something that far away!"));
return;
}
tx += ddx[dir];
g_ptr = &caster_ptr->current_floor_ptr->grid_array[ty][tx];
- if ((distance(caster_ptr->y, caster_ptr->x, ty, tx) > MAX_RANGE) || !cave_have_flag_bold(caster_ptr->current_floor_ptr, ty, tx, FF_PROJECT))
+ if ((distance(caster_ptr->y, caster_ptr->x, ty, tx) > get_max_range(caster_ptr))
+ || !cave_have_flag_bold(caster_ptr->current_floor_ptr, ty, tx, FF_PROJECT))
return;
}
}
}
/*!
- * @brief 全所持アイテム鑑定処理 /
- * Identify everything being carried.
- * Done by a potion of "self knowledge".
- * @param target_ptr プレーヤーへの参照ポインタ
- * @return なし
- */
-void identify_pack(player_type *target_ptr)
-{
- for (INVENTORY_IDX i = 0; i < INVEN_TOTAL; i++) {
- object_type *o_ptr = &target_ptr->inventory_list[i];
- if (!o_ptr->k_idx)
- continue;
-
- identify_item(target_ptr, o_ptr);
- autopick_alter_item(target_ptr, i, FALSE);
- }
-}
-
-/*!
- * @brief 装備の解呪処理 /
- * Removes curses from items in inventory
- * @param creature_ptr プレーヤーへの参照ポインタ
- * @param all 軽い呪いまでの解除ならば0
- * @return 解呪されたアイテムの数
- * @details
- * <pre>
- * Note that Items which are "Perma-Cursed" (The One Ring,
- * The Crown of Morgoth) can NEVER be uncursed.
- *
- * Note that if "all" is FALSE, then Items which are
- * "Heavy-Cursed" (Mormegil, Calris, and Weapons of Morgul)
- * will not be uncursed.
- * </pre>
- */
-static int remove_curse_aux(player_type *creature_ptr, int all)
-{
- int cnt = 0;
- for (int i = INVEN_RARM; i < INVEN_TOTAL; i++) {
- object_type *o_ptr = &creature_ptr->inventory_list[i];
- if (!o_ptr->k_idx)
- continue;
- if (!object_is_cursed(o_ptr))
- continue;
- if (!all && (o_ptr->curse_flags & TRC_HEAVY_CURSE))
- continue;
- if (o_ptr->curse_flags & TRC_PERMA_CURSE) {
- o_ptr->curse_flags &= (TRC_CURSED | TRC_HEAVY_CURSE | TRC_PERMA_CURSE);
- continue;
- }
-
- o_ptr->curse_flags = 0L;
- o_ptr->ident |= (IDENT_SENSE);
- o_ptr->feeling = FEEL_NONE;
-
- creature_ptr->update |= (PU_BONUS);
- creature_ptr->window |= (PW_EQUIP);
- cnt++;
- }
-
- if (cnt)
- msg_print(_("誰かに見守られているような気がする。", "You feel as if someone is watching over you."));
-
- return cnt;
-}
-
-/*!
- * @brief 装備の軽い呪い解呪処理 /
- * Remove most curses
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @return 解呪に成功した装備数
- */
-int remove_curse(player_type *caster_ptr) { return remove_curse_aux(caster_ptr, FALSE); }
-
-/*!
- * @brief 装備の重い呪い解呪処理 /
- * Remove all curses
- * @return 解呪に成功した装備数
- */
-int remove_all_curse(player_type *caster_ptr) { return remove_curse_aux(caster_ptr, TRUE); }
-
-/*!
* @brief アイテムの価値に応じた錬金術処理 /
* Turns an object into gold, gain some of its value in a shop
* @param caster_ptr プレーヤーへの参照ポインタ
o_ptr->number = old_number;
if (!force) {
- if (confirm_destroy || (object_value(o_ptr) > 0)) {
+ if (confirm_destroy || (object_value(caster_ptr, o_ptr) > 0)) {
char out_val[MAX_NLEN + 40];
sprintf(out_val, _("本当に%sを金に変えますか?", "Really turn %s to gold? "), o_name);
if (!get_check(out_val))
}
}
- if (!can_player_destroy_object(o_ptr)) {
+ if (!can_player_destroy_object(caster_ptr, o_ptr)) {
msg_format(_("%sを金に変えることに失敗した。", "You fail to turn %s to gold!"), o_name);
return FALSE;
}
- PRICE price = object_value_real(o_ptr);
+ PRICE price = object_value_real(caster_ptr, o_ptr);
if (price <= 0) {
msg_format(_("%sをニセの金に変えた。", "You turn %s to fool's gold."), o_name);
vary_item(caster_ptr, item, -amt);
}
/*!
- * @brief アイテム鑑定処理 /
- * Identify an object
- * @param owner_ptr プレーヤーへの参照ポインタ
- * @param o_ptr 鑑定されるアイテムの情報参照ポインタ
- * @return 実際に鑑定できたらTRUEを返す
- */
-bool identify_item(player_type *owner_ptr, object_type *o_ptr)
-{
- GAME_TEXT o_name[MAX_NLEN];
- object_desc(owner_ptr, o_name, o_ptr, 0);
-
- bool old_known = FALSE;
- if (o_ptr->ident & IDENT_KNOWN)
- old_known = TRUE;
-
- if (!object_is_fully_known(o_ptr)) {
- if (object_is_artifact(o_ptr) || one_in_(5))
- chg_virtue(owner_ptr, V_KNOWLEDGE, 1);
- }
-
- object_aware(owner_ptr, o_ptr);
- object_known(o_ptr);
- o_ptr->marked |= OM_TOUCHED;
-
- owner_ptr->update |= (PU_BONUS | PU_COMBINE | PU_REORDER);
- owner_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
-
- strcpy(record_o_name, o_name);
- record_turn = current_world_ptr->game_turn;
-
- object_desc(owner_ptr, o_name, o_ptr, OD_NAME_ONLY);
-
- if (record_fix_art && !old_known && object_is_fixed_artifact(o_ptr))
- exe_write_diary(owner_ptr, DIARY_ART, 0, o_name);
- if (record_rand_art && !old_known && o_ptr->art_name)
- exe_write_diary(owner_ptr, DIARY_ART, 0, o_name);
-
- return old_known;
-}
-
-/*!
- * @brief アイテム鑑定のメインルーチン処理 /
- * Identify an object in the inventory (or on the floor)
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @param only_equip 装備品のみを対象とするならばTRUEを返す
- * @return 実際に鑑定を行ったならばTRUEを返す
- * @details
- * This routine does *not* automatically combine objects.
- * Returns TRUE if something was identified, else FALSE.
- */
-bool ident_spell(player_type *caster_ptr, bool only_equip, tval_type item_tester_tval)
-{
- if (only_equip)
- item_tester_hook = item_tester_hook_identify_weapon_armour;
- else
- item_tester_hook = item_tester_hook_identify;
-
- concptr q;
- if (can_get_item(caster_ptr, item_tester_tval)) {
- q = _("どのアイテムを鑑定しますか? ", "Identify which item? ");
- } else {
- if (only_equip)
- item_tester_hook = object_is_weapon_armour_ammo;
- else
- item_tester_hook = NULL;
-
- q = _("すべて鑑定済みです。 ", "All items are identified. ");
- }
-
- concptr s = _("鑑定するべきアイテムがない。", "You have nothing to identify.");
- OBJECT_IDX item;
- object_type *o_ptr;
- o_ptr = choose_object(caster_ptr, &item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), 0);
- if (!o_ptr)
- return FALSE;
-
- bool old_known = identify_item(caster_ptr, o_ptr);
-
- GAME_TEXT o_name[MAX_NLEN];
- object_desc(caster_ptr, o_name, o_ptr, 0);
- if (item >= INVEN_RARM) {
- msg_format(_("%^s: %s(%c)。", "%^s: %s (%c)."), describe_use(caster_ptr, item), o_name, index_to_label(item));
- } else if (item >= 0) {
- msg_format(_("ザック中: %s(%c)。", "In your pack: %s (%c)."), o_name, index_to_label(item));
- } else {
- msg_format(_("床上: %s。", "On the ground: %s."), o_name);
- }
-
- autopick_alter_item(caster_ptr, item, (bool)(destroy_identify && !old_known));
- return TRUE;
-}
-
-/*!
* @brief アイテム凡庸化のメインルーチン処理 /
* Identify an object in the inventory (or on the floor)
* @param owner_ptr プレーヤーへの参照ポインタ
WEIGHT weight = o_ptr->number * o_ptr->weight;
u16b inscription = o_ptr->inscription;
- object_prep(o_ptr, o_ptr->k_idx);
+ object_prep(owner_ptr, o_ptr, o_ptr->k_idx);
o_ptr->iy = iy;
o_ptr->ix = ix;
}
/*!
- * @brief アイテム*鑑定*のメインルーチン処理 /
- * Identify an object in the inventory (or on the floor)
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @param only_equip 装備品のみを対象とするならばTRUEを返す
- * @return 実際に鑑定を行ったならばTRUEを返す
- * @details
- * Fully "identify" an object in the inventory -BEN-
- * This routine returns TRUE if an item was identified.
- */
-bool identify_fully(player_type *caster_ptr, bool only_equip, tval_type item_tester_tval)
-{
- if (only_equip)
- item_tester_hook = item_tester_hook_identify_fully_weapon_armour;
- else
- item_tester_hook = item_tester_hook_identify_fully;
-
- concptr q;
- if (can_get_item(caster_ptr, item_tester_tval)) {
- q = _("どのアイテムを*鑑定*しますか? ", "*Identify* which item? ");
- } else {
- if (only_equip)
- item_tester_hook = object_is_weapon_armour_ammo;
- else
- item_tester_hook = NULL;
-
- q = _("すべて*鑑定*済みです。 ", "All items are *identified*. ");
- }
-
- concptr s = _("*鑑定*するべきアイテムがない。", "You have nothing to *identify*.");
-
- OBJECT_IDX item;
- object_type *o_ptr;
- o_ptr = choose_object(caster_ptr, &item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR | IGNORE_BOTHHAND_SLOT), 0);
- if (!o_ptr)
- return FALSE;
-
- bool old_known = identify_item(caster_ptr, o_ptr);
-
- o_ptr->ident |= (IDENT_FULL_KNOWN);
- handle_stuff(caster_ptr);
-
- GAME_TEXT o_name[MAX_NLEN];
- object_desc(caster_ptr, o_name, o_ptr, 0);
- if (item >= INVEN_RARM) {
- msg_format(_("%^s: %s(%c)。", "%^s: %s (%c)."), describe_use(caster_ptr, item), o_name, index_to_label(item));
- } else if (item >= 0) {
- msg_format(_("ザック中: %s(%c)。", "In your pack: %s (%c)."), o_name, index_to_label(item));
- } else {
- msg_format(_("床上: %s。", "On the ground: %s."), o_name);
- }
-
- (void)screen_object(caster_ptr, o_ptr, 0L);
- autopick_alter_item(caster_ptr, item, (bool)(destroy_identify && !old_known));
- return TRUE;
-}
-
-/*!
* @brief 魔力充填処理 /
* Recharge a wand/staff/rod from the pack or on the floor.
* This function has been rewritten in Oangband and ZAngband.
}
/*!
- * @brief 呪文の経験値を返す /
- * Returns experience of a spell
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @param spell 呪文ID
- * @param use_realm 魔法領域
- * @return 経験値
- */
-EXP experience_of_spell(player_type *caster_ptr, SPELL_IDX spell, REALM_IDX use_realm)
-{
- if (caster_ptr->pclass == CLASS_SORCERER)
- return SPELL_EXP_MASTER;
- else if (caster_ptr->pclass == CLASS_RED_MAGE)
- return SPELL_EXP_SKILLED;
- else if (use_realm == caster_ptr->realm1)
- return caster_ptr->spell_exp[spell];
- else if (use_realm == caster_ptr->realm2)
- return caster_ptr->spell_exp[spell + 32];
- else
- return 0;
-}
-
-/*!
- * @brief 呪文の消費MPを返す /
- * Modify mana consumption rate using spell exp and dec_mana
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @param need_mana 基本消費MP
- * @param spell 呪文ID
- * @param realm 魔法領域
- * @return 消費MP
- */
-MANA_POINT mod_need_mana(player_type *caster_ptr, MANA_POINT need_mana, SPELL_IDX spell, REALM_IDX realm)
-{
-#define MANA_CONST 2400
-#define MANA_DIV 4
-#define DEC_MANA_DIV 3
- if ((realm > REALM_NONE) && (realm <= MAX_REALM)) {
- need_mana = need_mana * (MANA_CONST + SPELL_EXP_EXPERT - experience_of_spell(caster_ptr, spell, realm)) + (MANA_CONST - 1);
- need_mana *= caster_ptr->dec_mana ? DEC_MANA_DIV : MANA_DIV;
- need_mana /= MANA_CONST * MANA_DIV;
- if (need_mana < 1)
- need_mana = 1;
- } else {
- if (caster_ptr->dec_mana)
- need_mana = (need_mana + 1) * DEC_MANA_DIV / MANA_DIV;
- }
-
-#undef DEC_MANA_DIV
-#undef MANA_DIV
-#undef MANA_CONST
-
- return need_mana;
-}
-
-/*!
- * @brief 呪文の失敗率修正処理1(呪い、消費魔力減少、呪文簡易化) /
- * Modify spell fail rate
- * Using to_m_chance, dec_mana, easy_spell and heavy_spell
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @param chance 修正前失敗率
- * @return 失敗率(%)
- * @todo 統合を検討
- */
-PERCENTAGE mod_spell_chance_1(player_type *caster_ptr, PERCENTAGE chance)
-{
- chance += caster_ptr->to_m_chance;
-
- if (caster_ptr->heavy_spell)
- chance += 20;
-
- if (caster_ptr->dec_mana && caster_ptr->easy_spell)
- chance -= 4;
- else if (caster_ptr->easy_spell)
- chance -= 3;
- else if (caster_ptr->dec_mana)
- chance -= 2;
-
- return chance;
-}
-
-/*!
- * @brief 呪文の失敗率修正処理2(消費魔力減少、呪い、負値修正) /
- * Modify spell fail rate
- * Using to_m_chance, dec_mana, easy_spell and heavy_spell
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @param chance 修正前失敗率
- * @return 失敗率(%)
- * Modify spell fail rate (as "suffix" process)
- * Using dec_mana, easy_spell and heavy_spell
- * Note: variable "chance" cannot be negative.
- * @todo 統合を検討
- */
-PERCENTAGE mod_spell_chance_2(player_type *caster_ptr, PERCENTAGE chance)
-{
- if (caster_ptr->dec_mana)
- chance--;
- if (caster_ptr->heavy_spell)
- chance += 5;
- return MAX(chance, 0);
-}
-
-/*!
- * @brief 呪文の失敗率計算メインルーチン /
- * Returns spell chance of failure for spell -RAK-
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @param spell 呪文ID
- * @param use_realm 魔法領域ID
- * @return 失敗率(%)
- */
-PERCENTAGE spell_chance(player_type *caster_ptr, SPELL_IDX spell, REALM_IDX use_realm)
-{
- if (!mp_ptr->spell_book)
- return 100;
- if (use_realm == REALM_HISSATSU)
- return 0;
-
- const magic_type *s_ptr;
- if (!is_magic(use_realm)) {
- s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];
- } else {
- s_ptr = &mp_ptr->info[use_realm - 1][spell];
- }
-
- PERCENTAGE chance = s_ptr->sfail;
- chance -= 3 * (caster_ptr->lev - s_ptr->slevel);
- chance -= 3 * (adj_mag_stat[caster_ptr->stat_ind[mp_ptr->spell_stat]] - 1);
- if (caster_ptr->riding)
- chance += (MAX(r_info[caster_ptr->current_floor_ptr->m_list[caster_ptr->riding].r_idx].level - caster_ptr->skill_exp[GINOU_RIDING] / 100 - 10, 0));
-
- MANA_POINT need_mana = mod_need_mana(caster_ptr, s_ptr->smana, spell, use_realm);
- if (need_mana > caster_ptr->csp) {
- chance += 5 * (need_mana - caster_ptr->csp);
- }
-
- if ((use_realm != caster_ptr->realm1) && ((caster_ptr->pclass == CLASS_MAGE) || (caster_ptr->pclass == CLASS_PRIEST)))
- chance += 5;
-
- PERCENTAGE minfail = adj_mag_fail[caster_ptr->stat_ind[mp_ptr->spell_stat]];
- if (mp_ptr->spell_xtra & MAGIC_FAIL_5PERCENT) {
- if (minfail < 5)
- minfail = 5;
- }
-
- if (((caster_ptr->pclass == CLASS_PRIEST) || (caster_ptr->pclass == CLASS_SORCERER)) && caster_ptr->icky_wield[0])
- chance += 25;
- if (((caster_ptr->pclass == CLASS_PRIEST) || (caster_ptr->pclass == CLASS_SORCERER)) && caster_ptr->icky_wield[1])
- chance += 25;
-
- chance = mod_spell_chance_1(caster_ptr, chance);
- PERCENTAGE penalty = (mp_ptr->spell_stat == A_WIS) ? 10 : 4;
- switch (use_realm) {
- case REALM_NATURE:
- if ((caster_ptr->align > 50) || (caster_ptr->align < -50))
- chance += penalty;
- break;
- case REALM_LIFE:
- case REALM_CRUSADE:
- if (caster_ptr->align < -20)
- chance += penalty;
- break;
- case REALM_DEATH:
- case REALM_DAEMON:
- case REALM_HEX:
- if (caster_ptr->align > 20)
- chance += penalty;
- break;
- }
-
- if (chance < minfail)
- chance = minfail;
-
- if (caster_ptr->stun > 50)
- chance += 25;
- else if (caster_ptr->stun)
- chance += 15;
-
- if (chance > 95)
- chance = 95;
-
- if ((use_realm == caster_ptr->realm1) || (use_realm == caster_ptr->realm2) || (caster_ptr->pclass == CLASS_SORCERER)
- || (caster_ptr->pclass == CLASS_RED_MAGE)) {
- EXP exp = experience_of_spell(caster_ptr, spell, use_realm);
- if (exp >= SPELL_EXP_EXPERT)
- chance--;
- if (exp >= SPELL_EXP_MASTER)
- chance--;
- }
-
- return mod_spell_chance_2(caster_ptr, chance);
-}
-
-/*!
- * @brief 呪文情報の表示処理 /
- * Print a list of spells (for browsing or casting or viewing)
- * @param caster_ptr 術者の参照ポインタ
- * @param target_spell 呪文ID
- * @param spells 表示するスペルID配列の参照ポインタ
- * @param num 表示するスペルの数(spellsの要素数)
- * @param y 表示メッセージ左上Y座標
- * @param x 表示メッセージ左上X座標
- * @param use_realm 魔法領域ID
- * @return なし
- */
-void print_spells(player_type *caster_ptr, SPELL_IDX target_spell, SPELL_IDX *spells, int num, TERM_LEN y, TERM_LEN x, REALM_IDX use_realm)
-{
- if (((use_realm <= REALM_NONE) || (use_realm > MAX_REALM)) && current_world_ptr->wizard)
- msg_print(_("警告! print_spell が領域なしに呼ばれた", "Warning! print_spells called with null realm"));
-
- prt("", y, x);
- char buf[256];
- if (use_realm == REALM_HISSATSU)
- strcpy(buf, _(" Lv MP", " Lv SP"));
- else
- strcpy(buf, _("熟練度 Lv MP 失率 効果", "Profic Lv SP Fail Effect"));
-
- put_str(_("名前", "Name"), y, x + 5);
- put_str(buf, y, x + 29);
-
- int increment = 64;
- if ((caster_ptr->pclass == CLASS_SORCERER) || (caster_ptr->pclass == CLASS_RED_MAGE))
- increment = 0;
- else if (use_realm == caster_ptr->realm1)
- increment = 0;
- else if (use_realm == caster_ptr->realm2)
- increment = 32;
-
- int i;
- int exp_level;
- const magic_type *s_ptr;
- char info[80];
- char out_val[160];
- char ryakuji[5];
- bool max = FALSE;
- for (i = 0; i < num; i++) {
- SPELL_IDX spell = spells[i];
-
- if (!is_magic(use_realm)) {
- s_ptr = &technic_info[use_realm - MIN_TECHNIC][spell];
- } else {
- s_ptr = &mp_ptr->info[use_realm - 1][spell];
- }
-
- MANA_POINT need_mana;
- if (use_realm == REALM_HISSATSU)
- need_mana = s_ptr->smana;
- else {
- EXP exp = experience_of_spell(caster_ptr, spell, use_realm);
- need_mana = mod_need_mana(caster_ptr, s_ptr->smana, spell, use_realm);
- if ((increment == 64) || (s_ptr->slevel >= 99))
- exp_level = EXP_LEVEL_UNSKILLED;
- else
- exp_level = spell_exp_level(exp);
-
- max = FALSE;
- if (!increment && (exp_level == EXP_LEVEL_MASTER))
- max = TRUE;
- else if ((increment == 32) && (exp_level >= EXP_LEVEL_EXPERT))
- max = TRUE;
- else if (s_ptr->slevel >= 99)
- max = TRUE;
- else if ((caster_ptr->pclass == CLASS_RED_MAGE) && (exp_level >= EXP_LEVEL_SKILLED))
- max = TRUE;
-
- strncpy(ryakuji, exp_level_str[exp_level], 4);
- ryakuji[3] = ']';
- ryakuji[4] = '\0';
- }
-
- if (use_menu && target_spell) {
- if (i == (target_spell - 1))
- strcpy(out_val, _(" 》 ", " > "));
- else
- strcpy(out_val, " ");
- } else
- sprintf(out_val, " %c) ", I2A(i));
-
- if (s_ptr->slevel >= 99) {
- strcat(out_val, format("%-30s", _("(判読不能)", "(illegible)")));
- c_prt(TERM_L_DARK, out_val, y + i + 1, x);
- continue;
- }
-
- strcpy(info, exe_spell(caster_ptr, use_realm, spell, SPELL_INFO));
- concptr comment = info;
- byte line_attr = TERM_WHITE;
- if ((caster_ptr->pclass == CLASS_SORCERER) || (caster_ptr->pclass == CLASS_RED_MAGE)) {
- if (s_ptr->slevel > caster_ptr->max_plv) {
- comment = _("未知", "unknown");
- line_attr = TERM_L_BLUE;
- } else if (s_ptr->slevel > caster_ptr->lev) {
- comment = _("忘却", "forgotten");
- line_attr = TERM_YELLOW;
- }
- } else if ((use_realm != caster_ptr->realm1) && (use_realm != caster_ptr->realm2)) {
- comment = _("未知", "unknown");
- line_attr = TERM_L_BLUE;
- } else if ((use_realm == caster_ptr->realm1) ? ((caster_ptr->spell_forgotten1 & (1L << spell))) : ((caster_ptr->spell_forgotten2 & (1L << spell)))) {
- comment = _("忘却", "forgotten");
- line_attr = TERM_YELLOW;
- } else if (!((use_realm == caster_ptr->realm1) ? (caster_ptr->spell_learned1 & (1L << spell)) : (caster_ptr->spell_learned2 & (1L << spell)))) {
- comment = _("未知", "unknown");
- line_attr = TERM_L_BLUE;
- } else if (!((use_realm == caster_ptr->realm1) ? (caster_ptr->spell_worked1 & (1L << spell)) : (caster_ptr->spell_worked2 & (1L << spell)))) {
- comment = _("未経験", "untried");
- line_attr = TERM_L_GREEN;
- }
-
- if (use_realm == REALM_HISSATSU) {
- strcat(out_val, format("%-25s %2d %4d", exe_spell(caster_ptr, use_realm, spell, SPELL_NAME), s_ptr->slevel, need_mana));
- } else {
- strcat(out_val,
- format("%-25s%c%-4s %2d %4d %3d%% %s", exe_spell(caster_ptr, use_realm, spell, SPELL_NAME), (max ? '!' : ' '), ryakuji, s_ptr->slevel,
- need_mana, spell_chance(caster_ptr, spell, use_realm), comment));
- }
-
- c_prt(line_attr, out_val, y + i + 1, x);
- }
-
- prt("", y + i + 1, x);
-}
-
-/*!
* @brief 変身処理向けにモンスターの近隣レベル帯モンスターを返す /
* Helper function -- return a "nearby" race for polymorphing
* @param floor_ptr 配置するフロアの参照ポインタ
}
/*!
- * @brief 魔力食い処理
- * @param caster_ptr プレーヤーへの参照ポインタ
- * @param power 基本効力
- * @return ターンを消費した場合TRUEを返す
- */
-bool eat_magic(player_type *caster_ptr, int power)
-{
- byte fail_type = 1;
- GAME_TEXT o_name[MAX_NLEN];
-
- item_tester_hook = item_tester_hook_recharge;
-
- concptr q = _("どのアイテムから魔力を吸収しますか?", "Drain which item? ");
- concptr s = _("魔力を吸収できるアイテムがありません。", "You have nothing to drain.");
-
- object_type *o_ptr;
- OBJECT_IDX item;
- o_ptr = choose_object(caster_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), 0);
- if (!o_ptr)
- return FALSE;
-
- object_kind *k_ptr;
- k_ptr = &k_info[o_ptr->k_idx];
- DEPTH lev = k_info[o_ptr->k_idx].level;
-
- int recharge_strength = 0;
- bool is_eating_successful = TRUE;
- if (o_ptr->tval == TV_ROD) {
- recharge_strength = ((power > lev / 2) ? (power - lev / 2) : 0) / 5;
- if (one_in_(recharge_strength)) {
- is_eating_successful = FALSE;
- } else {
- if (o_ptr->timeout > (o_ptr->number - 1) * k_ptr->pval) {
- msg_print(_("充填中のロッドから魔力を吸収することはできません。", "You can't absorb energy from a discharged rod."));
- } else {
- caster_ptr->csp += lev;
- o_ptr->timeout += k_ptr->pval;
- }
- }
- } else {
- recharge_strength = (100 + power - lev) / 15;
- if (recharge_strength < 0)
- recharge_strength = 0;
-
- if (one_in_(recharge_strength)) {
- is_eating_successful = FALSE;
- } else {
- if (o_ptr->pval > 0) {
- caster_ptr->csp += lev / 2;
- o_ptr->pval--;
-
- if ((o_ptr->tval == TV_STAFF) && (item >= 0) && (o_ptr->number > 1)) {
- object_type forge;
- object_type *q_ptr;
- q_ptr = &forge;
- object_copy(q_ptr, o_ptr);
-
- q_ptr->number = 1;
- o_ptr->pval++;
- o_ptr->number--;
- caster_ptr->total_weight -= q_ptr->weight;
- item = store_item_to_inventory(caster_ptr, q_ptr);
-
- msg_print(_("杖をまとめなおした。", "You unstack your staff."));
- }
- } else {
- msg_print(_("吸収できる魔力がありません!", "There's no energy there to absorb!"));
- }
-
- if (!o_ptr->pval)
- o_ptr->ident |= IDENT_EMPTY;
- }
- }
-
- if (is_eating_successful) {
- return redraw_player(caster_ptr);
- }
-
- if (object_is_fixed_artifact(o_ptr)) {
- object_desc(caster_ptr, o_name, o_ptr, OD_NAME_ONLY);
- msg_format(_("魔力が逆流した!%sは完全に魔力を失った。", "The recharging backfires - %s is completely drained!"), o_name);
- if (o_ptr->tval == TV_ROD)
- o_ptr->timeout = k_ptr->pval * o_ptr->number;
- else if ((o_ptr->tval == TV_WAND) || (o_ptr->tval == TV_STAFF))
- o_ptr->pval = 0;
-
- return redraw_player(caster_ptr);
- }
-
- object_desc(caster_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
-
- /* Mages recharge objects more safely. */
- if (IS_WIZARD_CLASS(caster_ptr)) {
- /* 10% chance to blow up one rod, otherwise draining. */
- if (o_ptr->tval == TV_ROD) {
- if (one_in_(10))
- fail_type = 2;
- else
- fail_type = 1;
- }
- /* 75% chance to blow up one wand, otherwise draining. */
- else if (o_ptr->tval == TV_WAND) {
- if (!one_in_(3))
- fail_type = 2;
- else
- fail_type = 1;
- }
- /* 50% chance to blow up one staff, otherwise no effect. */
- else if (o_ptr->tval == TV_STAFF) {
- if (one_in_(2))
- fail_type = 2;
- else
- fail_type = 0;
- }
- }
-
- /* All other classes get no special favors. */
- else {
- /* 33% chance to blow up one rod, otherwise draining. */
- if (o_ptr->tval == TV_ROD) {
- if (one_in_(3))
- fail_type = 2;
- else
- fail_type = 1;
- }
- /* 20% chance of the entire stack, else destroy one wand. */
- else if (o_ptr->tval == TV_WAND) {
- if (one_in_(5))
- fail_type = 3;
- else
- fail_type = 2;
- }
- /* Blow up one staff. */
- else if (o_ptr->tval == TV_STAFF) {
- fail_type = 2;
- }
- }
-
- if (fail_type == 1) {
- if (o_ptr->tval == TV_ROD) {
- msg_format(_("ロッドは破損を免れたが、魔力は全て失なわれた。", "You save your rod from destruction, but all charges are lost."), o_name);
- o_ptr->timeout = k_ptr->pval * o_ptr->number;
- } else if (o_ptr->tval == TV_WAND) {
- msg_format(_("%sは破損を免れたが、魔力が全て失われた。", "You save your %s from destruction, but all charges are lost."), o_name);
- o_ptr->pval = 0;
- }
- }
-
- if (fail_type == 2) {
- if (o_ptr->number > 1) {
- msg_format(_("乱暴な魔法のために%sが一本壊れた!", "Wild magic consumes one of your %s!"), o_name);
- /* Reduce rod stack maximum timeout, drain wands. */
- if (o_ptr->tval == TV_ROD)
- o_ptr->timeout = MIN(o_ptr->timeout, k_ptr->pval * (o_ptr->number - 1));
- else if (o_ptr->tval == TV_WAND)
- o_ptr->pval = o_ptr->pval * (o_ptr->number - 1) / o_ptr->number;
- } else {
- msg_format(_("乱暴な魔法のために%sが何本か壊れた!", "Wild magic consumes your %s!"), o_name);
- }
-
- vary_item(caster_ptr, item, -1);
- }
-
- if (fail_type == 3) {
- if (o_ptr->number > 1)
- msg_format(_("乱暴な魔法のために%sが全て壊れた!", "Wild magic consumes all your %s!"), o_name);
- else
- msg_format(_("乱暴な魔法のために%sが壊れた!", "Wild magic consumes your %s!"), o_name);
-
- vary_item(caster_ptr, item, -999);
- }
-
- return redraw_player(caster_ptr);
-}
-
-/*!
* @brief 皆殺し(全方向攻撃)処理
* @param caster_ptr プレーヤーへの参照ポインタ
* @return なし
m_ptr = &caster_ptr->current_floor_ptr->m_list[m_idx];
monster_desc(caster_ptr, m_name, m_ptr, 0);
msg_format(_("%sを引き戻した。", "You pull back %s."), m_name);
- path_n = project_path(caster_ptr, path_g, MAX_RANGE, target_row, target_col, caster_ptr->y, caster_ptr->x, 0);
+ path_n = project_path(caster_ptr, path_g, get_max_range(caster_ptr), target_row, target_col, caster_ptr->y, caster_ptr->x, 0);
ty = target_row, tx = target_col;
for (i = 1; i < path_n; i++) {
POSITION ny = GRID_Y(path_g[i]);
tx = nx;
}
}
- /* Update the old location */
- caster_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx = 0;
- /* Update the new location */
+ caster_ptr->current_floor_ptr->grid_array[target_row][target_col].m_idx = 0;
caster_ptr->current_floor_ptr->grid_array[ty][tx].m_idx = m_idx;
-
- /* Move the monster */
m_ptr->fy = ty;
m_ptr->fx = tx;
-
- /* Wake the monster up */
(void)set_monster_csleep(caster_ptr, m_idx, 0);
-
update_monster(caster_ptr, m_idx, TRUE);
lite_spot(caster_ptr, target_row, target_col);
lite_spot(caster_ptr, ty, tx);
-
if (r_info[m_ptr->r_idx].flags7 & (RF7_LITE_MASK | RF7_DARK_MASK))
caster_ptr->update |= (PU_MON_LITE);
if (m_ptr->ml) {
- /* Auto-Recall if possible and visible */
if (!caster_ptr->image)
monster_race_track(caster_ptr, m_ptr->ap_r_idx);
+
health_track(caster_ptr, m_idx);
}
+
return TRUE;
}
screen_load();
return TRUE;
}
-
-static bool update_player(player_type *caster_ptr)
-{
- caster_ptr->update |= PU_COMBINE | PU_REORDER;
- caster_ptr->window |= PW_INVEN;
- return TRUE;
-}
-
-static bool redraw_player(player_type *caster_ptr)
-{
- if (caster_ptr->csp > caster_ptr->msp) {
- caster_ptr->csp = caster_ptr->msp;
- }
-
- caster_ptr->redraw |= PR_MANA;
- caster_ptr->update |= PU_COMBINE | PU_REORDER;
- caster_ptr->window |= PW_INVEN;
- return TRUE;
-}