OSDN Git Service

f2b1291bef14fc112a5224b17cb0e1c37bf7cced
[hengbandforosx/hengbandosx.git] / src / wizard / fixed-artifacts-spoiler.cpp
1 #include "wizard/fixed-artifacts-spoiler.h"
2 #include "io/files-util.h"
3 #include "object/object-kind-hook.h"
4 #include "system/angband-version.h"
5 #include "system/artifact-type-definition.h"
6 #include "system/baseitem-info.h"
7 #include "system/item-entity.h"
8 #include "system/player-type-definition.h"
9 #include "util/angband-files.h"
10 #include "view/display-messages.h"
11 #include "wizard/artifact-analyzer.h"
12 #include "wizard/spoiler-util.h"
13
14 /*!
15  * @brief フラグ名称を出力する汎用関数
16  * @param header ヘッダに出力するフラグ群の名前
17  * @param list フラグ名リスト
18  * @param separator フラグ表示の区切り記号
19  * @todo 固定アーティファクトとランダムアーティファクトで共用、ここに置くべきかは要調整.
20  */
21 void spoiler_outlist(concptr header, concptr *list, char separator)
22 {
23     if (*list == nullptr) {
24         return;
25     }
26
27     std::string line = spoiler_indent;
28     if (header && (header[0])) {
29         line.append(header).append(" ");
30     }
31
32     while (true) {
33         std::string elem = *list;
34         if (list[1]) {
35             elem.push_back(separator);
36             elem.push_back(' ');
37         }
38
39         if (line.length() + elem.length() <= MAX_LINE_LEN) {
40             line.append(elem);
41         } else {
42             if (line.length() > 1 && line[line.length() - 1] == ' ' && line[line.length() - 2] == list_separator) {
43                 line[line.length() - 2] = '\0';
44                 fprintf(spoiler_file, "%s\n", line.data());
45                 line = spoiler_indent;
46                 line.append(elem);
47             } else {
48                 fprintf(spoiler_file, "%s\n", line.data());
49                 line = "      ";
50                 line.append(elem);
51             }
52         }
53
54         if (!*++list) {
55             break;
56         }
57     }
58
59     fprintf(spoiler_file, "%s\n", line.data());
60 }
61
62 /*!
63  * @brief アーティファクト情報を出力するためにダミー生成を行う /
64  * Hack -- Create a "forged" artifact
65  * @param o_ptr 一時生成先を保管するオブジェクト構造体
66  * @param fixed_artifact_idx 生成するアーティファクトID
67  * @return 生成が成功した場合TRUEを返す
68  */
69 static bool make_fake_artifact(ItemEntity *o_ptr, FixedArtifactId fixed_artifact_idx)
70 {
71     auto &a_ref = artifacts_info.at(fixed_artifact_idx);
72     if (a_ref.name.empty()) {
73         return false;
74     }
75
76     const auto bi_id = lookup_baseitem_id(a_ref.bi_key);
77     if (bi_id == 0) {
78         return false;
79     }
80
81     o_ptr->prep(bi_id);
82     o_ptr->fixed_artifact_idx = fixed_artifact_idx;
83     o_ptr->pval = a_ref.pval;
84     o_ptr->ac = a_ref.ac;
85     o_ptr->dd = a_ref.dd;
86     o_ptr->ds = a_ref.ds;
87     o_ptr->to_a = a_ref.to_a;
88     o_ptr->to_h = a_ref.to_h;
89     o_ptr->to_d = a_ref.to_d;
90     o_ptr->weight = a_ref.weight;
91     return true;
92 }
93
94 /*!
95  * @brief アーティファクト一件をスポイラー出力する /
96  * Create a spoiler file entry for an artifact
97  * @param art_ptr アーティファクト情報をまとめた構造体の参照ポインタ
98  */
99 static void spoiler_print_art(obj_desc_list *art_ptr)
100 {
101     pval_info_type *pval_ptr = &art_ptr->pval_info;
102     fprintf(spoiler_file, "%s\n", art_ptr->description);
103     if (pval_ptr->pval_desc[0]) {
104         spoiler_outlist(std::string(pval_ptr->pval_desc).append(_("の修正:", " to")).data(), pval_ptr->pval_affects, item_separator);
105     }
106
107     spoiler_outlist(_("対:", "Slay"), art_ptr->slays, item_separator);
108     spoiler_outlist(_("武器属性:", ""), art_ptr->brands, list_separator);
109     spoiler_outlist(_("免疫:", "Immunity to"), art_ptr->immunities, item_separator);
110     spoiler_outlist(_("耐性:", "Resist"), art_ptr->resistances, item_separator);
111     spoiler_outlist(_("弱点:", "Vulnerable"), art_ptr->vulnerables, item_separator);
112     spoiler_outlist(_("維持:", "Sustain"), art_ptr->sustains, item_separator);
113     spoiler_outlist("", art_ptr->misc_magic, list_separator);
114
115     if (art_ptr->addition[0]) {
116         fprintf(spoiler_file, _("%s追加: %s\n", "%sAdditional %s\n"), spoiler_indent, art_ptr->addition);
117     }
118
119     if (art_ptr->activation) {
120         fprintf(spoiler_file, _("%s発動: %s\n", "%sActivates for %s\n"), spoiler_indent, art_ptr->activation);
121     }
122
123     fprintf(spoiler_file, "%s%s\n\n", spoiler_indent, art_ptr->misc_desc);
124 }
125
126 /*!
127  * @brief アーティファクト情報のスポイラー出力を行うメインルーチン /
128  * Create a spoiler file for artifacts
129  * @param fname 生成ファイル名
130  */
131 SpoilerOutputResultType spoil_fixed_artifact(concptr fname)
132 {
133     char buf[1024];
134     path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
135     spoiler_file = angband_fopen(buf, FileOpenMode::WRITE);
136     if (!spoiler_file) {
137         return SpoilerOutputResultType::FILE_OPEN_FAILED;
138     }
139
140     spoiler_underline(std::string("Artifact Spoilers for Hengband Version ").append(get_version()).data());
141     for (const auto &[tval_list, name] : group_artifact_list) {
142         spoiler_blanklines(2);
143         spoiler_underline(name);
144         spoiler_blanklines(1);
145
146         for (auto tval : tval_list) {
147             for (const auto &[a_idx, a_ref] : artifacts_info) {
148                 if (a_ref.bi_key.tval() != tval) {
149                     continue;
150                 }
151
152                 ItemEntity item;
153                 if (!make_fake_artifact(&item, a_idx)) {
154                     continue;
155                 }
156
157                 PlayerType dummy;
158                 obj_desc_list artifact;
159                 object_analyze(&dummy, &item, &artifact);
160                 spoiler_print_art(&artifact);
161             }
162         }
163     }
164
165     return ferror(spoiler_file) || angband_fclose(spoiler_file) ? SpoilerOutputResultType::FILE_CLOSE_FAILED
166                                                                 : SpoilerOutputResultType::SUCCESSFUL;
167 }