<ClCompile Include="..\..\src\core\status-reseter.c" />\r
<ClCompile Include="..\..\src\core\visuals-reseter.c" />\r
<ClCompile Include="..\..\src\core\window-redrawer.c" />\r
+ <ClCompile Include="..\..\src\dungeon\quest-completion-checker.c" />\r
<ClCompile Include="..\..\src\dungeon\quest-monster-placer.c" />\r
<ClCompile Include="..\..\src\flavor\flag-inscriptions-table.c" />\r
<ClCompile Include="..\..\src\flavor\flavor-describer.c" />\r
<ClInclude Include="..\..\src\core\visuals-reseter.h" />\r
<ClInclude Include="..\..\src\core\window-redrawer.h" />\r
<ClInclude Include="..\..\src\dungeon\dungeon-flag-types.h" />\r
+ <ClInclude Include="..\..\src\dungeon\quest-completion-checker.h" />\r
<ClInclude Include="..\..\src\dungeon\quest-monster-placer.h" />\r
<ClInclude Include="..\..\src\flavor\flag-inscriptions-table.h" />\r
<ClInclude Include="..\..\src\flavor\flavor-describer.h" />\r
<ClCompile Include="..\..\src\monster-floor\monster-lite.c">
<Filter>monster-floor</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\dungeon\quest-completion-checker.c">
+ <Filter>dungeon</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\combat\shoot.h">
<ClInclude Include="..\..\src\monster-floor\monster-lite.h">
<Filter>monster-floor</Filter>
</ClInclude>
+ <ClInclude Include="..\..\src\dungeon\quest-completion-checker.h">
+ <Filter>dungeon</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\src\wall.bmp" />
dungeon/dungeon-flag-types.h \
dungeon/dungeon-processor.c dungeon/dungeon-processor.h \
dungeon/quest.h dungeon/quest.c \
+ dungeon/quest-completion-checker.c dungeon/quest-completion-checker.h \
dungeon/quest-monster-placer.c dungeon/quest-monster-placer.h \
\
effect/effect-feature.c effect/effect-feature.h \
--- /dev/null
+#include "dungeon/quest-completion-checker.h"
+#include "core/player-update-types.h"
+#include "dungeon/quest.h"
+#include "floor/cave.h"
+#include "floor/floor-object.h"
+#include "floor/floor.h"
+#include "grid/feature-flag-types.h"
+#include "grid/feature.h"
+#include "grid/grid.h"
+#include "monster/monster-info.h"
+#include "object-enchant/item-apply-magic.h"
+#include "object/object-generator.h"
+#include "system/floor-type-definition.h"
+#include "system/monster-type-definition.h"
+#include "view/display-messages.h"
+
+/*!
+ * @brief 現在フロアに残っている敵モンスターの数を返す /
+ * @return 現在の敵モンスターの数
+ */
+static MONSTER_NUMBER count_all_hostile_monsters(floor_type *floor_ptr)
+{
+ MONSTER_NUMBER number_mon = 0;
+ for (POSITION x = 0; x < floor_ptr->width; ++x) {
+ for (POSITION y = 0; y < floor_ptr->height; ++y) {
+ MONSTER_IDX m_idx = floor_ptr->grid_array[y][x].m_idx;
+ if (m_idx > 0 && is_hostile(&floor_ptr->m_list[m_idx]))
+ ++number_mon;
+ }
+ }
+
+ return number_mon;
+}
+
+/*!
+ * @brief 特定の敵を倒した際にクエスト達成処理 /
+ * Check for "Quest" completion when a quest monster is killed or charmed.
+ * @param player_ptr プレーヤーへの参照ポインタ
+ * @param m_ptr 撃破したモンスターの構造体参照ポインタ
+ * @return なし
+ */
+void check_quest_completion(player_type *player_ptr, monster_type *m_ptr)
+{
+ POSITION y = m_ptr->fy;
+ POSITION x = m_ptr->fx;
+ floor_type *floor_ptr = player_ptr->current_floor_ptr;
+ QUEST_IDX quest_num = floor_ptr->inside_quest;
+ if (!quest_num) {
+ QUEST_IDX i;
+ for (i = max_q_idx - 1; i > 0; i--) {
+ quest_type *const q_ptr = &quest[i];
+ if (q_ptr->status != QUEST_STATUS_TAKEN)
+ continue;
+
+ if (q_ptr->flags & QUEST_FLAG_PRESET)
+ continue;
+
+ if ((q_ptr->level != floor_ptr->dun_level) && (q_ptr->type != QUEST_TYPE_KILL_ANY_LEVEL))
+ continue;
+
+ if ((q_ptr->type == QUEST_TYPE_FIND_ARTIFACT) || (q_ptr->type == QUEST_TYPE_FIND_EXIT))
+ continue;
+
+ if ((q_ptr->type == QUEST_TYPE_KILL_NUMBER) || (q_ptr->type == QUEST_TYPE_TOWER) || (q_ptr->type == QUEST_TYPE_KILL_ALL))
+ break;
+
+ if (((q_ptr->type == QUEST_TYPE_KILL_LEVEL) || (q_ptr->type == QUEST_TYPE_KILL_ANY_LEVEL) || (q_ptr->type == QUEST_TYPE_RANDOM))
+ && (q_ptr->r_idx == m_ptr->r_idx))
+ break;
+ }
+
+ quest_num = i;
+ }
+
+ bool create_stairs = FALSE;
+ bool reward = FALSE;
+ if (quest_num && (quest[quest_num].status == QUEST_STATUS_TAKEN)) {
+ quest_type *const q_ptr = &quest[quest_num];
+ switch (q_ptr->type) {
+ case QUEST_TYPE_KILL_NUMBER: {
+ q_ptr->cur_num++;
+ if (q_ptr->cur_num >= q_ptr->num_mon) {
+ complete_quest(player_ptr, quest_num);
+ q_ptr->cur_num = 0;
+ }
+
+ break;
+ }
+ case QUEST_TYPE_KILL_ALL: {
+ if (!is_hostile(m_ptr) || count_all_hostile_monsters(floor_ptr) != 1)
+ break;
+
+ if (q_ptr->flags & QUEST_FLAG_SILENT) {
+ q_ptr->status = QUEST_STATUS_FINISHED;
+ } else {
+ complete_quest(player_ptr, quest_num);
+ }
+
+ break;
+ }
+ case QUEST_TYPE_KILL_LEVEL:
+ case QUEST_TYPE_RANDOM: {
+ if (q_ptr->r_idx != m_ptr->r_idx)
+ break;
+
+ q_ptr->cur_num++;
+ if (q_ptr->cur_num < q_ptr->max_num)
+ break;
+
+ complete_quest(player_ptr, quest_num);
+ if (!(q_ptr->flags & QUEST_FLAG_PRESET)) {
+ create_stairs = TRUE;
+ floor_ptr->inside_quest = 0;
+ }
+
+ if ((quest_num == QUEST_OBERON) || (quest_num == QUEST_SERPENT))
+ q_ptr->status = QUEST_STATUS_FINISHED;
+
+ if (q_ptr->type == QUEST_TYPE_RANDOM) {
+ reward = TRUE;
+ q_ptr->status = QUEST_STATUS_FINISHED;
+ }
+
+ break;
+ }
+ case QUEST_TYPE_KILL_ANY_LEVEL: {
+ q_ptr->cur_num++;
+ if (q_ptr->cur_num >= q_ptr->max_num) {
+ complete_quest(player_ptr, quest_num);
+ q_ptr->cur_num = 0;
+ }
+
+ break;
+ }
+ case QUEST_TYPE_TOWER: {
+ if (!is_hostile(m_ptr))
+ break;
+
+ if (count_all_hostile_monsters(floor_ptr) == 1) {
+ q_ptr->status = QUEST_STATUS_STAGE_COMPLETED;
+
+ if ((quest[QUEST_TOWER1].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[QUEST_TOWER2].status == QUEST_STATUS_STAGE_COMPLETED)
+ && (quest[QUEST_TOWER3].status == QUEST_STATUS_STAGE_COMPLETED)) {
+
+ complete_quest(player_ptr, QUEST_TOWER1);
+ }
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (create_stairs) {
+ POSITION ny, nx;
+ while (cave_have_flag_bold(floor_ptr, y, x, FF_PERMANENT) || floor_ptr->grid_array[y][x].o_idx || (floor_ptr->grid_array[y][x].info & CAVE_OBJECT)) {
+ scatter(player_ptr, &ny, &nx, y, x, 1, 0);
+ y = ny;
+ x = nx;
+ }
+
+ msg_print(_("魔法の階段が現れた...", "A magical staircase appears..."));
+ cave_set_feat(player_ptr, y, x, feat_down_stair);
+ player_ptr->update |= PU_FLOW;
+ }
+
+ if (!reward)
+ return;
+
+ object_type forge;
+ object_type *o_ptr;
+ for (int i = 0; i < (floor_ptr->dun_level / 15) + 1; i++) {
+ o_ptr = &forge;
+ object_wipe(o_ptr);
+ make_object(player_ptr, o_ptr, AM_GOOD | AM_GREAT);
+ (void)drop_near(player_ptr, o_ptr, -1, y, x);
+ }
+}
--- /dev/null
+#pragma once
+
+#include "system/angband.h"
+
+typedef struct monster_type monster_type;
+void check_quest_completion(player_type *player_ptr, monster_type *m_ptr);
}
/*!
- * @brief 特定の敵を倒した際にクエスト達成処理 /
- * Check for "Quest" completion when a quest monster is killed or charmed.
- * @param player_ptr プレーヤーへの参照ポインタ
- * @param m_ptr 撃破したモンスターの構造体参照ポインタ
- * @return なし
- */
-void check_quest_completion(player_type *player_ptr, monster_type *m_ptr)
-{
- POSITION y = m_ptr->fy;
- POSITION x = m_ptr->fx;
- floor_type *floor_ptr = player_ptr->current_floor_ptr;
- QUEST_IDX quest_num = floor_ptr->inside_quest;
- if (!quest_num) {
- QUEST_IDX i;
- for (i = max_q_idx - 1; i > 0; i--) {
- quest_type *const q_ptr = &quest[i];
- if (q_ptr->status != QUEST_STATUS_TAKEN)
- continue;
-
- if (q_ptr->flags & QUEST_FLAG_PRESET)
- continue;
-
- if ((q_ptr->level != floor_ptr->dun_level) && (q_ptr->type != QUEST_TYPE_KILL_ANY_LEVEL))
- continue;
-
- if ((q_ptr->type == QUEST_TYPE_FIND_ARTIFACT) || (q_ptr->type == QUEST_TYPE_FIND_EXIT))
- continue;
-
- if ((q_ptr->type == QUEST_TYPE_KILL_NUMBER) || (q_ptr->type == QUEST_TYPE_TOWER) || (q_ptr->type == QUEST_TYPE_KILL_ALL))
- break;
-
- if (((q_ptr->type == QUEST_TYPE_KILL_LEVEL) || (q_ptr->type == QUEST_TYPE_KILL_ANY_LEVEL) || (q_ptr->type == QUEST_TYPE_RANDOM))
- && (q_ptr->r_idx == m_ptr->r_idx))
- break;
- }
-
- quest_num = i;
- }
-
- bool create_stairs = FALSE;
- bool reward = FALSE;
- if (quest_num && (quest[quest_num].status == QUEST_STATUS_TAKEN)) {
- quest_type *const q_ptr = &quest[quest_num];
- switch (q_ptr->type) {
- case QUEST_TYPE_KILL_NUMBER: {
- q_ptr->cur_num++;
- if (q_ptr->cur_num >= q_ptr->num_mon) {
- complete_quest(player_ptr, quest_num);
- q_ptr->cur_num = 0;
- }
-
- break;
- }
- case QUEST_TYPE_KILL_ALL: {
- if (!is_hostile(m_ptr) || count_all_hostile_monsters(floor_ptr) != 1)
- break;
-
- if (q_ptr->flags & QUEST_FLAG_SILENT) {
- q_ptr->status = QUEST_STATUS_FINISHED;
- } else {
- complete_quest(player_ptr, quest_num);
- }
-
- break;
- }
- case QUEST_TYPE_KILL_LEVEL:
- case QUEST_TYPE_RANDOM: {
- if (q_ptr->r_idx != m_ptr->r_idx)
- break;
-
- q_ptr->cur_num++;
- if (q_ptr->cur_num < q_ptr->max_num)
- break;
-
- complete_quest(player_ptr, quest_num);
- if (!(q_ptr->flags & QUEST_FLAG_PRESET)) {
- create_stairs = TRUE;
- floor_ptr->inside_quest = 0;
- }
-
- if ((quest_num == QUEST_OBERON) || (quest_num == QUEST_SERPENT))
- q_ptr->status = QUEST_STATUS_FINISHED;
-
- if (q_ptr->type == QUEST_TYPE_RANDOM) {
- reward = TRUE;
- q_ptr->status = QUEST_STATUS_FINISHED;
- }
-
- break;
- }
- case QUEST_TYPE_KILL_ANY_LEVEL: {
- q_ptr->cur_num++;
- if (q_ptr->cur_num >= q_ptr->max_num) {
- complete_quest(player_ptr, quest_num);
- q_ptr->cur_num = 0;
- }
-
- break;
- }
- case QUEST_TYPE_TOWER: {
- if (!is_hostile(m_ptr))
- break;
-
- if (count_all_hostile_monsters(floor_ptr) == 1) {
- q_ptr->status = QUEST_STATUS_STAGE_COMPLETED;
-
- if ((quest[QUEST_TOWER1].status == QUEST_STATUS_STAGE_COMPLETED) && (quest[QUEST_TOWER2].status == QUEST_STATUS_STAGE_COMPLETED)
- && (quest[QUEST_TOWER3].status == QUEST_STATUS_STAGE_COMPLETED)) {
-
- complete_quest(player_ptr, QUEST_TOWER1);
- }
- }
-
- break;
- }
- }
- }
-
- if (create_stairs) {
- POSITION ny, nx;
- while (cave_have_flag_bold(floor_ptr, y, x, FF_PERMANENT) || floor_ptr->grid_array[y][x].o_idx || (floor_ptr->grid_array[y][x].info & CAVE_OBJECT)) {
- scatter(player_ptr, &ny, &nx, y, x, 1, 0);
- y = ny;
- x = nx;
- }
-
- msg_print(_("魔法の階段が現れた...", "A magical staircase appears..."));
- cave_set_feat(player_ptr, y, x, feat_down_stair);
- player_ptr->update |= (PU_FLOW);
- }
-
- if (!reward)
- return;
-
- object_type forge;
- object_type *o_ptr;
- for (int i = 0; i < (floor_ptr->dun_level / 15) + 1; i++) {
- o_ptr = &forge;
- object_wipe(o_ptr);
- make_object(player_ptr, o_ptr, AM_GOOD | AM_GREAT);
- (void)drop_near(player_ptr, o_ptr, -1, y, x);
- }
-}
-
-/*!
* @brief 特定のアーティファクトを入手した際のクエスト達成処理 /
* Check for "Quest" completion when a quest monster is killed or charmed.
* @param player_ptr プレーヤーへの参照ポインタ
extern int quest_text_line;
extern int leaving_quest;
-extern void determine_random_questor(player_type *player_ptr, quest_type *q_ptr);
-extern void complete_quest(player_type *player_ptr, QUEST_IDX quest_num);
-extern void check_quest_completion(player_type *player_ptr, monster_type *m_ptr);
-extern void check_find_art_quest_completion(player_type *player_ptr, object_type *o_ptr);
-extern void quest_discovery(QUEST_IDX q_idx);
-extern QUEST_IDX quest_number(player_type *player_ptr, DEPTH level);
-extern QUEST_IDX random_quest_number(player_type *player_ptr, DEPTH level);
-extern void leave_quest_check(player_type *player_ptr);
-extern void leave_tower_check(player_type *player_ptr);
-extern void do_cmd_quest(player_type *player_ptr);
+void determine_random_questor(player_type *player_ptr, quest_type *q_ptr);
+void complete_quest(player_type *player_ptr, QUEST_IDX quest_num);
+void check_find_art_quest_completion(player_type *player_ptr, object_type *o_ptr);
+void quest_discovery(QUEST_IDX q_idx);
+QUEST_IDX quest_number(player_type *player_ptr, DEPTH level);
+QUEST_IDX random_quest_number(player_type *player_ptr, DEPTH level);
+void leave_quest_check(player_type *player_ptr);
+void leave_tower_check(player_type *player_ptr);
+void do_cmd_quest(player_type *player_ptr);
}
/*!
- * @brief 現在フロアに残っている敵モンスターの数を返す /
- * @return 現在の敵モンスターの数
- */
-MONSTER_NUMBER count_all_hostile_monsters(floor_type *floor_ptr)
-{
- MONSTER_NUMBER number_mon = 0;
- for (POSITION x = 0; x < floor_ptr->width; ++x) {
- for (POSITION y = 0; y < floor_ptr->height; ++y) {
- MONSTER_IDX m_idx = floor_ptr->grid_array[y][x].m_idx;
- if (m_idx > 0 && is_hostile(&floor_ptr->m_list[m_idx]))
- ++number_mon;
- }
- }
-
- return number_mon;
-}
-
-/*!
* ダンジョンの雰囲気を計算するための非線形基準値 / Dungeon rating is no longer linear
*/
static int rating_boost(int delta) { return delta * delta + 50 * delta; }
void day_break(player_type *subject_ptr);
void night_falls(player_type *subject_ptr);
-MONSTER_NUMBER count_all_hostile_monsters(floor_type *floor_ptr);
void update_dungeon_feeling(player_type *subject_ptr);
void glow_deep_lava_and_bldg(player_type *subject_ptr);
void forget_lite(floor_type *floor_ptr);
#include "core/player-redraw-types.h"
#include "core/player-update-types.h"
#include "dungeon/dungeon.h"
-#include "dungeon/quest.h"
+#include "dungeon/quest-completion-checker.h"
#include "effect/effect-characteristics.h"
#include "floor/cave.h"
#include "floor/floor-object.h"
#include "monster-floor/monster-runaway.h"
#include "core/disturbance.h"
-#include "dungeon/quest.h"
+#include "dungeon/quest-completion-checker.h"
#include "floor/cave.h"
#include "floor/floor.h"
#include "grid/grid.h"
*/
#include "monster/monster-info.h"
-#include "dungeon/quest.h"
+#include "dungeon/quest-completion-checker.h" // todo 相互依存.
#include "floor/cave.h"
#include "floor/wild.h"
#include "grid/feature.h"
/*!
+ * todo ここがcheck_quest_completion() を呼んでいるのが相互依存の原因。infoなのにsetしているのがおかしい、後で修正する.
* @brief モンスターをペットにする
* @param player_type プレーヤーへの参照ポインタ
* @param m_ptr モンスター情報構造体の参照ポインタ
#include "core/asking-player.h"
#include "core/player-redraw-types.h"
#include "dungeon/dungeon.h"
+#include "dungeon/quest-completion-checker.h"
#include "dungeon/quest.h"
#include "floor/cave.h"
#include "floor/floor-save.h"