OSDN Git Service

[Refactor] #37353 バリアント名称とバージョン定義を core.h へ移動.
[hengband/hengband.git] / src / quest.c
index 0ec1728..ffa270b 100644 (file)
@@ -1,8 +1,37 @@
 #include "angband.h"
+#include "util.h"
+
+#include "core.h"
+#include "floor.h"
+#include "floor-save.h"
 #include "floor-events.h"
+#include "grid.h"
 #include "quest.h"
 #include "monsterrace-hook.h"
+#include "monster.h"
+#include "player-status.h"
+#include "artifact.h"
+#include "feature.h"
+#include "world.h"
+#include "cmd-dump.h"
+
+quest_type *quest; /*!< Quest info */
+QUEST_IDX max_q_idx; /*!< Maximum number of quests */
+char quest_text[10][80]; /*!< Quest text */
+int quest_text_line; /*!< Current line of the quest text */
+int leaving_quest = 0;
 
+/*!
+ * @brief クエスト突入時のメッセージテーブル / Array of places to find an inscription
+ */
+static concptr find_quest[] =
+{
+       _("床にメッセージが刻まれている:", "You find the following inscription in the floor"),
+       _("壁にメッセージが刻まれている:", "You see a message inscribed in the wall"),
+       _("メッセージを見つけた:", "There is a sign saying"),
+       _("何かが階段の上に書いてある:", "Something is written on the staircase"),
+       _("巻物を見つけた。メッセージが書いてある:", "You find a scroll with the following message"),
+};
 
 /*!
  * @brief ランダムクエストの討伐ユニークを決める / Determine the random quest uniques
@@ -65,7 +94,7 @@ void complete_quest(QUEST_IDX quest_num)
        q_ptr->status = QUEST_STATUS_COMPLETED;
        q_ptr->complev = p_ptr->lev;
        update_playtime();
-       q_ptr->comptime = playtime;
+       q_ptr->comptime = current_world_ptr->play_time;
 
        if (!(q_ptr->flags & QUEST_FLAG_SILENT))
        {
@@ -118,7 +147,7 @@ void check_quest_completion(monster_type *m_ptr)
                                continue;
 
                        /* Quest is not on this level */
-                       if ((q_ptr->level != dun_level) &&
+                       if ((q_ptr->level != current_floor_ptr->dun_level) &&
                                (q_ptr->type != QUEST_TYPE_KILL_ANY_LEVEL))
                                continue;
 
@@ -251,7 +280,7 @@ void check_quest_completion(monster_type *m_ptr)
                POSITION ny, nx;
 
                /* Stagger around */
-               while (cave_perma_bold(y, x) || cave[y][x].o_idx || (cave[y][x].info & CAVE_OBJECT))
+               while (cave_perma_bold(y, x) || current_floor_ptr->grid_array[y][x].o_idx || (current_floor_ptr->grid_array[y][x].info & CAVE_OBJECT))
                {
                        /* Pick a location */
                        scatter(&ny, &nx, y, x, 1, 0);
@@ -277,7 +306,7 @@ void check_quest_completion(monster_type *m_ptr)
        {
                int i;
 
-               for (i = 0; i < (dun_level / 15) + 1; i++)
+               for (i = 0; i < (current_floor_ptr->dun_level / 15) + 1; i++)
                {
                        o_ptr = &forge;
                        object_wipe(o_ptr);
@@ -311,6 +340,50 @@ void check_find_art_quest_completion(object_type *o_ptr)
 }
 
 
+/*!
+ * @brief クエストの導入メッセージを表示する / Discover quest
+ * @param q_idx 開始されたクエストのID
+ */
+void quest_discovery(QUEST_IDX q_idx)
+{
+       quest_type *q_ptr = &quest[q_idx];
+       monster_race *r_ptr = &r_info[q_ptr->r_idx];
+       MONSTER_NUMBER q_num = q_ptr->max_num;
+       GAME_TEXT name[MAX_NLEN];
+
+       if (!q_idx) return;
+
+       strcpy(name, (r_name + r_ptr->name));
+
+       msg_print(find_quest[rand_range(0, 4)]);
+       msg_print(NULL);
+
+       if (q_num == 1)
+       {
+               if ((r_ptr->flags1 & RF1_UNIQUE) && (0 == r_ptr->max_num))
+               {
+                       msg_print(_("この階は以前は誰かによって守られていたようだ…。", "It seems that this level was protected by someone before..."));
+                       /* The unique is already dead */
+                       quest[q_idx].status = QUEST_STATUS_FINISHED;
+                       q_ptr->complev = 0;
+                       update_playtime();
+                       q_ptr->comptime = current_world_ptr->play_time;
+               }
+               else
+               {
+                       msg_format(_("注意せよ!この階は%sによって守られている!", "Beware, this level is protected by %s!"), name);
+               }
+       }
+       else
+       {
+#ifndef JP
+               plural_aux(name);
+#endif
+               msg_format(_("注意しろ!この階は%d体の%sによって守られている!", "Be warned, this level is guarded by %d %s!"), q_num, name);
+
+       }
+}
+
 
 /*!
  * @brief 新しく入ったダンジョンの階層に固定されている一般のクエストを探し出しIDを返す。
@@ -333,7 +406,7 @@ QUEST_IDX quest_number(DEPTH level)
                if ((quest[i].type == QUEST_TYPE_KILL_LEVEL) &&
                        !(quest[i].flags & QUEST_FLAG_PRESET) &&
                        (quest[i].level == level) &&
-                       (quest[i].dungeon == dungeon_type))
+                       (quest[i].dungeon == p_ptr->dungeon_idx))
                        return (i);
        }
 
@@ -350,7 +423,7 @@ QUEST_IDX random_quest_number(DEPTH level)
 {
        QUEST_IDX i;
 
-       if (dungeon_type != DUNGEON_ANGBAND) return 0;
+       if (p_ptr->dungeon_idx != DUNGEON_ANGBAND) return 0;
 
        for (i = MIN_RANDOM_QUEST; i < MAX_RANDOM_QUEST + 1; i++)
        {
@@ -365,3 +438,116 @@ QUEST_IDX random_quest_number(DEPTH level)
 
        return 0;
 }
+
+/*!
+ * @brief クエスト階層から離脱する際の処理
+ * @return なし
+ */
+void leave_quest_check(void)
+{
+       /* Save quest number for dungeon pref file ($LEAVING_QUEST) */
+       leaving_quest = p_ptr->inside_quest;
+
+       /* Leaving an 'only once' quest marks it as failed */
+       if (leaving_quest)
+       {
+               quest_type* const q_ptr = &quest[leaving_quest];
+
+               if (((q_ptr->flags & QUEST_FLAG_ONCE) || (q_ptr->type == QUEST_TYPE_RANDOM)) &&
+                       (q_ptr->status == QUEST_STATUS_TAKEN))
+               {
+                       q_ptr->status = QUEST_STATUS_FAILED;
+                       q_ptr->complev = p_ptr->lev;
+                       update_playtime();
+                       q_ptr->comptime = current_world_ptr->play_time;
+
+                       /* Additional settings */
+                       switch (q_ptr->type)
+                       {
+                       case QUEST_TYPE_TOWER:
+                               quest[QUEST_TOWER1].status = QUEST_STATUS_FAILED;
+                               quest[QUEST_TOWER1].complev = p_ptr->lev;
+                               break;
+                       case QUEST_TYPE_FIND_ARTIFACT:
+                               a_info[q_ptr->k_idx].gen_flags &= ~(TRG_QUESTITEM);
+                               break;
+                       case QUEST_TYPE_RANDOM:
+                               r_info[q_ptr->r_idx].flags1 &= ~(RF1_QUESTOR);
+
+                               /* Floor of random quest will be blocked */
+                               prepare_change_floor_mode(CFM_NO_RETURN);
+                               break;
+                       }
+
+                       /* Record finishing a quest */
+                       if (q_ptr->type == QUEST_TYPE_RANDOM)
+                       {
+                               if (record_rand_quest) do_cmd_write_nikki(NIKKI_RAND_QUEST_F, leaving_quest, NULL);
+                       }
+                       else
+                       {
+                               if (record_fix_quest) do_cmd_write_nikki(NIKKI_FIX_QUEST_F, leaving_quest, NULL);
+                       }
+               }
+       }
+}
+
+/*!
+ * @brief 「塔」クエストの各階層から離脱する際の処理
+ * @return なし
+ */
+void leave_tower_check(void)
+{
+       leaving_quest = p_ptr->inside_quest;
+       /* Check for Tower Quest */
+       if (leaving_quest &&
+               (quest[leaving_quest].type == QUEST_TYPE_TOWER) &&
+               (quest[QUEST_TOWER1].status != QUEST_STATUS_COMPLETED))
+       {
+               if (quest[leaving_quest].type == QUEST_TYPE_TOWER)
+               {
+                       quest[QUEST_TOWER1].status = QUEST_STATUS_FAILED;
+                       quest[QUEST_TOWER1].complev = p_ptr->lev;
+                       update_playtime();
+                       quest[QUEST_TOWER1].comptime = current_world_ptr->play_time;
+               }
+       }
+}
+
+
+/*!
+ * @brief クエスト入り口にプレイヤーが乗った際の処理 / Do building commands
+ * @return なし
+ */
+void do_cmd_quest(void)
+{
+       if (p_ptr->wild_mode) return;
+
+       take_turn(p_ptr, 100);
+
+       if (!cave_have_flag_bold(p_ptr->y, p_ptr->x, FF_QUEST_ENTER))
+       {
+               msg_print(_("ここにはクエストの入口はない。", "You see no quest level here."));
+               return;
+       }
+       else
+       {
+               msg_print(_("ここにはクエストへの入口があります。", "There is an entry of a quest."));
+               if (!get_check(_("クエストに入りますか?", "Do you enter? "))) return;
+               if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (p_ptr->inventory_list[INVEN_BOW].name1 == ART_CRIMSON))
+                       msg_print(_("『とにかく入ってみようぜぇ。』", ""));
+               else if (p_ptr->pseikaku == SEIKAKU_CHARGEMAN) msg_print("『全滅してやるぞ!』");
+
+               /* Player enters a new quest */
+               p_ptr->oldpy = 0;
+               p_ptr->oldpx = 0;
+
+               leave_quest_check();
+
+               if (quest[p_ptr->inside_quest].type != QUEST_TYPE_RANDOM) current_floor_ptr->dun_level = 1;
+               p_ptr->inside_quest = current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].special;
+
+               p_ptr->leaving = TRUE;
+       }
+}
+