2018/12/03
■ [変愚蛮怒/開発]変愚蛮怒用インターフェース拡張の可能性
これはRoguelike Advent Calendar 2018 3日目の記事です。
はじめに
今年もAdvent Calenderの季節がやってまいりました。 一昨年とか去年とかの進行に関する記事を見直しながらやはり溜息つくのが現状であります。
冒頭から私事の愚痴で恐縮なのですが、ここ数年は実の所リアルの事情が停滞でじり貧でした。逆に今年からは逆に良い方にも悪い方にも振れ幅が大きすぎて頭抱えることが多く、中々に続けるものを続けることが困難な日々が続いております。
どうにか他の人々のご厚意受けて立て直したいとまだ考えてはいるのでどうぞよろしく。
過去の関連記事
本ブログの記事を見直すに4年以上前には現状のWindowsAPIを拡張する形で、あれこれやろうとして(実際BGM機能は既存先人のものを改良できたりしましたが)頓挫しっぱなしになっていたりします。
また、マルチプラットホームに関する件については過去のAdvent Calenderの記事にもした
などがあります。
現状のインターフェースについて
しばしば某所で言われますし、それで当然とは思われますが、現状変愚が直接はZangbandから引き継いできた旧WindowsAPIによるCursesの延長上を意識したテキストインターフェースも昔から色々限界になっております。 何分往年の主力であったDirectXすら使わない、恐らくはWindows98時代基準のAPI採用です。
テキストだけで完結できるシステムというのが、恐らく今ですら全くメリットがないとは言えないとは思います。現に本家Angbandは現行でもGNU系Cursesやでのビルドも可能なようですし、ANSI準拠のCが走る環境をサポートする態勢も確保しているようです。
とは言え平成も終わろうとしているこのご時世にいい加減にテキストのままも虚しいですよね。その点も含み本家は64ドットタイルにも対応していますがZangbandなどを挟み、フォークとして遠く離れてしまった変愚はここから恩恵を受けることなく、独自路線で行くしかありません。
そのZangから受け取ったインターフェースの構造はどんなもんでしょうか。一重にz-form.hの構造体にまとまっています。
/*! * @brief term実装構造体 / An actual "term" structure */ typedef struct term term; struct term { vptr user; //!< Extra "user" info (used by application) vptr data; //!< Extra "data" info (used by implementation) bool user_flag; //!< Flag "user_flag" An extra "user" flag (used by application) bool data_flag; //!< Flag "data_flag" An extra "data" flag (used by implementation) bool active_flag; //!< Flag "active_flag" This "term" is "active" bool mapped_flag; //!< Flag "mapped_flag" This "term" is "mapped" bool total_erase; //!< Flag "total_erase" This "term" should be fully erased bool fixed_shape; //!< Flag "fixed_shape" This "term" is not allowed to resize bool icky_corner; //!< Flag "icky_corner" This "term" has an "icky" corner grid bool soft_cursor; //!< Flag "soft_cursor" This "term" uses a "software" cursor bool always_pict; //!< Flag "always_pict" Use the "Term_pict()" routine for all text bool higher_pict; //!< Flag "higher_pict" Use the "Term_pict()" routine for special text bool always_text; //!< Flag "always_text" Use the "Term_text()" routine for invisible text bool unused_flag; //!< Flag "unused_flag" Reserved for future use bool never_bored; //!< Flag "never_bored" Never call the "TERM_XTRA_BORED" action bool never_frosh; //!< Flag "never_frosh" Never call the "TERM_XTRA_FROSH" action byte attr_blank; //!< Value "attr_blank" Use this "attr" value for "blank" grids char char_blank; //!< Value "char_blank" Use this "char" value for "blank" grids char *key_queue; //!< Keypress Queue -- various data / Keypress Queue -- pending keys u16b key_head; u16b key_tail; u16b key_xtra; u16b key_size; TERM_LEN wid; //!< Window Width(max 255) TERM_LEN hgt; //!< Window Height(max 255) TERM_LEN y1; //!< Minimum modified row TERM_LEN y2; //!< Maximum modified row TERM_LEN *x1; //!< Minimum modified column(per row) TERM_LEN *x2; //!< Maximum modified column(per row) term_win *old; //!< Displayed screen image term_win *scr; //!< Requested screen image term_win *tmp; //!< Temporary screen image term_win *mem; //!< Memorized screen image void (*init_hook)(term *t); //!< Hook for init - ing the term void (*nuke_hook)(term *t); //!< Hook for nuke - ing the term errr (*user_hook)(int n); //!< ユーザ設定項目実装部 / Hook for user actions errr (*xtra_hook)(int n, int v); //!< 拡張機能実装部 / Hook for extra actions errr (*curs_hook)(TERM_LEN x, TERM_LEN y); //!< カーソル描画実装部 / Hook for placing the cursor errr (*bigcurs_hook)(TERM_LEN x, TERM_LEN y); //!< 大型タイル時カーソル描画実装部 / Hook for placing the cursor on bigtile mode errr (*wipe_hook)(TERM_LEN x, TERM_LEN y, int n); //!< 指定座標テキスト消去実装部 / Hook for drawing some blank spaces errr (*text_hook)(TERM_LEN x, TERM_LEN y, int n, TERM_COLOR a, cptr s); //!< テキスト描画実装部 / Hook for drawing a string of chars using an attr void (*resize_hook)(void); //!< 画面リサイズ実装部 errr (*pict_hook)(TERM_LEN x, TERM_LEN y, int n, TERM_COLOR *ap, const char *cp, const TERM_COLOR *tap, const char *tcp); //!< タイル描画実装部 / Hook for drawing a sequence of special attr / char pairs };
一応インターフェースの抽象化と言う奴はこれで一通りできてはいるんですね。ここの後半を占める関数ポインタでTerm(テキスト画面)の描画や消去を行い、前半で各インターフェースの性質に応じた処理の行い分けも実現は出来ている。
これを前の記事で述べたmain-???.c各自が実装することでWindows版、UNIX/Linuxのcurses版やx11版、古いMac版などが成り立っている次第です。
逆に言えば、この構造体の中身を新規にmain-???.cで埋め尽くせば、ひとまずは新しいインターフェースが作成できることになります。今回それの候補を考えるとどうなるかなのですが。
SDL(特に2.0系)
今やSteamでも鳴らして久しいToME先輩やAngband大先輩もどうも対応しているらしい選択肢です。 私自身馴染みがある、といいますかそもそもD'angbandだなんて、残骸になりかけている方でらしいインターフェースは作ったりしています。
こちらも大概変愚ソース改変から始まっていたり、かと思ったらフルスクラッチでやったり迷走している有様なのですが、じゃあここで作ったリソースを少しでも変愚の方に還元するのもありかなと。
いっそUnity使えや
もうSDLもレガシーにも程がある遺産な訳で今から手を付けるのならいっそ一足飛びに最近のスタンダードになりつつあるUnityに飛び込むのもありなのかもしれません。
個人的に、こちとら技術の進歩と流行りに取り残されて悶絶している最中ですが、将来の本業としてあるいはここでその一足飛びをかますのもありでしょう。さしあたってネイティブプラグインという選択肢はあるようですし。
最後に
どれでもいいからいい加減計画は立てるだけでなく軌道修正しながら実現しましょう。
カレンダー4日目はp31xxx氏のCAVES OF QUDの紹介となります。
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part96…リファクタリング
ノーコメント。
- Mon Dec 3 23:57:22 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Mon Dec 3 23:52:59 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Mon Dec 3 23:47:46 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Mon Dec 3 23:39:49 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Mon Dec 3 23:31:06 2018 +0900: [Refactor] #37353 mon_take_hit() のコメントアウト済落馬処理を削除。 / Delete comment outed process in mon_take_hit().
- Sun Dec 2 23:56:57 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
2018/12/04
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part97…リファクタリング
骸骨が骨を食糧代わりにするという古い処理を見かけたりしたがとりあえず削除。
- Tue Dec 4 20:43:11 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Tue Dec 4 20:12:28 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Tue Dec 4 20:00:20 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Tue Dec 4 19:44:57 2018 +0900: [Refactor] #37353 #if 0 プリプロセッサ削除 / Delete #if 0 code.
- Tue Dec 4 19:34:06 2018 +0900: [Refactor] #37454 デバッグコード削除 / Delete debug code.
- Tue Dec 4 19:20:36 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Tue Dec 4 19:09:39 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Tue Dec 4 19:03:09 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Tue Dec 4 07:59:21 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
2018/12/06
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part98…リファクタリング
こればっかやっている時は大体時間に困っていて、これすらできていない時はさらに時間ないの。ゆ る し て。
- Fri Dec 7 00:03:00 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Thu Dec 6 23:55:48 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Thu Dec 6 23:45:27 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Thu Dec 6 23:32:16 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Thu Dec 6 23:24:13 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
2018/12/07
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part99…特別編「変愚蛮怒の性格実装例 ~かわいそうなお友達~」
はじめに
変愚蛮怒がまさにソースコードの違法建築物であり、拡張に色々手を付けづらいのは事実なのですが、その中でも「性格」の実装はまだしも追加しないといけない処理が少なく、比較的手軽に実装が出来るのもまた確かです。
という訳で今回は全く趣味に走り、某超個性派レトロアニメの要素をモンスターだけでなくプレイヤー側に実現する手順を見てみましょう。
このネタは今や停滞して久しい拙バリアントD'angの旧ソースにも一応組み込んだことのあるものです。
ブランチ
という訳でOSDNのリポジトリにこんなブランチを作りました。今回は本当に即興なので、本流には調整やデバッグ済ませてからマージします。
基礎ステータス設定
まず特に最低限の部分だけ済ませましょう。性格のステータス修正を追加します。
defines.hにある性格の定義数を直しIDを定義します。
diff --git a/src/defines.h b/src/defines.h index ec8e7db..4cf51fe 100644 --- a/src/defines.h +++ b/src/defines.h @@ -181,7 +181,7 @@ #define MAX_OWNERS 32 /*!< 各店舗毎の店主定義最大数 / Total number of owners per store (see "store.c", etc) */ #define MAX_SEXES 2 /*!< 性別の定義最大数 / Maximum number of player "sex" types (see "table.c", etc) */ #define MAX_CLASS 28 /*!< 職業の最大定義数 Maximum number of player "class" types (see "table.c", etc) */ -#define MAX_SEIKAKU 12 /*!< 性格の最大定義数 */ +#define MAX_SEIKAKU 13 /*!< 性格の最大定義数 */ #define MAX_PATRON 16 /*!< カオスパトロンの最大定義数 / The number of "patrons" available (for Chaos Warriors) */ /* ELDRITCH_HORRORによるsanity blast処理に関するメッセージの最大数 / Number of entries in the sanity-blast descriptions */ @@ -825,6 +825,7 @@ #define SEIKAKU_LUCKY 9 #define SEIKAKU_GAMAN 10 #define SEIKAKU_MUNCHKIN 11 +#define SEIKAKU_CHARGEMAN 12
tables.cにある性格ステータス修正テーブルにも追加します。seikaku_info構造体は以下の通りです。
typedef struct player_seikaku player_seikaku; struct player_seikaku { cptr title; /* Type of seikaku */ #ifdef JP cptr E_title; /* 英語性格 */ #endif s16b a_adj[6]; /* seikaku stat bonuses */ s16b a_dis; /* seikaku disarming */ s16b a_dev; /* seikaku magic devices */ s16b a_sav; /* seikaku saving throw */ s16b a_stl; /* seikaku stealth */ s16b a_srh; /* seikaku search ability */ s16b a_fos; /* seikaku search frequency */ s16b a_thn; /* seikaku combat (normal) */ s16b a_thb; /* seikaku combat (shooting) */ s16b a_mhp; /* Race hit-dice modifier */ byte no; /* の */ byte sex; /* seibetu seigen */ };
大体、ちからじまんといのちしらずのメリットデメリットを足して極端にしてみました。
diff --git a/src/tables.c b/src/tables.c index cbb707d..71ec372 100644 --- a/src/tables.c +++ b/src/tables.c @@ -3240,6 +3240,17 @@ const player_seikaku seikaku_info[MAX_SEIKAKU] = 20, 40, 30, 10, 40, 40, 80, 80, 15, 1, 0 }, + + { +#ifdef JP + "チャージマン", +#endif + "Chargeman", + { 2, -2, -2, 0, 1, -2 }, + -7, 7, -5, -1, -2, -4, 15, 20, + -1, 0, 0 + }, + }; --
最後にキャラメイク時の解説追加です。ガバガバ英語 ゆ る し て
diff --git a/src/birth.c b/src/birth.c index 8a92971..2cbd48e 100644 --- a/src/birth.c +++ b/src/birth.c @@ -347,6 +347,8 @@ static cptr seikaku_jouhou[MAX_SEIKAKU] = "いかさまは、初心者の練習用の性格です。あらゆる能力が高くなっています。この性格を使えば勝利者になることは容易ですが、勝利しても全く自慢になりません。", +"チャージマンは「こんなところ」に連れて行かれても仕方のない可愛そうなお友達なんDA。腕っ節やタフさはマンモス並みに強いのだけれど知能面はまるで駄目なのが分かるだろう?この性格は最初から気が狂っているので、混乱したり幻覚を見る心配がないのです。", + #else "\"Ordinary\" is a personality with no special skills or talents, with unmodified stats and skills.", @@ -372,7 +374,10 @@ static cptr seikaku_jouhou[MAX_SEIKAKU] = "A \"Patient\" person does things carefully. Patient people have high constitution, and high resilience, but poor abilities in most other skills. Also it directly influences your hit-points.", -"\"munchkin\" is a personality for beginners. It raises all your stats and skills. With this personality, you can win the game easily, but gain little honor in doing so." +"\"munchkin\" is a personality for beginners. It raises all your stats and skills. With this personality, you can win the game easily, but gain little honor in doing so.", + +"\ChargeMan\" is crazy killer. It render you powerfull strength and constitution, but poor intelligence.you are not confused and seen the illusion because this you go mad from the beginning.", + #endif };
以上でこうして性格がキャラメイク時に指定できるまでは可能になります。
基礎特性修正
続けて上記の馴レーションで解説している通り、頭が元からお詳しいので、混乱耐性と幻覚耐性を持たせてみます。
耐性などの付加は種族、職業、性格などを問わずxtra1.cのcalc_bonuses()で追加できます。
diff --git a/src/xtra1.c b/src/xtra1.c index fcb013a..e708b2c 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -3860,10 +3860,17 @@ void calc_bonuses(void) /* Sexy Gal */ if (p_ptr->pseikaku == SEIKAKU_SEXY) p_ptr->cursed |= (TRC_AGGRAVATE); + if (p_ptr->pseikaku == SEIKAKU_NAMAKE) p_ptr->to_m_chance += 10; if (p_ptr->pseikaku == SEIKAKU_KIREMONO) p_ptr->to_m_chance -= 3; if ((p_ptr->pseikaku == SEIKAKU_GAMAN) || (p_ptr->pseikaku == SEIKAKU_CHIKARA)) p_ptr->to_m_chance++; + if (p_ptr->pseikaku == SEIKAKU_CHARGEMAN) + { + p_ptr->to_m_chance += 5; + p_ptr->resist_conf = TRUE; + } + /* Lucky man */ if (p_ptr->pseikaku == SEIKAKU_LUCKY) p_ptr->muta3 |= MUT3_GOOD_LUCK; --
それとは別に files.cのplayer_flags()関数でCコマンドで表示される処理も追加しなければなりません。
diff --git a/src/files.c b/src/files.c index f27b2da..4c016d9 100644 --- a/src/files.c +++ b/src/files.c @@ -2588,6 +2588,8 @@ static void player_flags(BIT_FLAGS flgs[TR_FLAG_SIZE]) if (p_ptr->pseikaku == SEIKAKU_SEXY) add_flag(flgs, TR_AGGRAVATE); + if (p_ptr->pseikaku == SEIKAKU_CHARGEMAN) + add_flag(flgs, TR_RES_CONF); if (p_ptr->pseikaku == SEIKAKU_MUNCHKIN) { add_flag(flgs, TR_RES_BLIND);
幻覚耐性については、ゴーレムやアンデッドが出血を抑止されるのと同様、set_image()関数で常に値を0にする処理で実装しましょう。
diff --git a/src/effects.c b/src/effects.c index 5f391f3..ef781a0 100644 --- a/src/effects.c +++ b/src/effects.c @@ -697,6 +697,7 @@ bool set_image(TIME_EFFECT v) v = (v > 10000) ? 10000 : (v < 0) ? 0 : v; if (p_ptr->is_dead) return FALSE; + if (p_ptr->pseikaku == SEIKAKU_CHARGEMAN) v = 0; /* Open */
以下のように@さん自身の先天的体質として表示されます。
台詞変化
あの「コンバット」に劣らぬ個性なのですから台詞の変化も欲しい所、大体、PSEIKAKU_COMBATで見つかる処理から、チャージマン向けに使えそうなメッセージをつうずるっこみます。
diff --git a/src/bldg.c b/src/bldg.c index f8d9975..0b57b9d 100644 --- a/src/bldg.c +++ b/src/bldg.c @@ -4353,6 +4353,7 @@ void do_cmd_quest(void) if (!get_check(_("クエストに入りますか?", "Do you enter? "))) return; if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON)) msg_print(_("『とにかく入ってみようぜぇ。』", "")); + else if(p_ptr->pseikaku == SEIKAKU_CHARGEMAN) msg_print("『全滅してやるぞ!』"); diff --git a/src/mspells4.c b/src/mspells4.c index a0a31c3..d7f267f 100644 --- a/src/mspells4.c +++ b/src/mspells4.c @@ -229,6 +229,11 @@ void spell_RF4_DISPEL(MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE) if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON)) msg_print(_("やりやがったな!", "")); + else if ((p_ptr->pseikaku == SEIKAKU_CHARGEMAN)) + { + if (randint0(2) == 0) msg_print(_("ジュラル星人め!", "")); + else msg_print(_("弱い者いじめは止めるんだ!", "")); + } learn_spell(MS_DISPEL); } @@ -2267,7 +2272,12 @@ void spell_RF6_TELE_AWAY(MONSTER_IDX m_idx, MONSTER_IDX t_idx, int TARGET_TYPE) { if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON)) msg_print(_("くっそ~", "")); - + else if ((p_ptr->pseikaku == SEIKAKU_CHARGEMAN)) + { + if (randint0(2) == 0) msg_print(_("ジュラル星人め!", "")); + else msg_print(_("弱い者いじめは止めるんだ!", "")); + } + learn_spell(MS_TELE_AWAY); teleport_player_away(m_idx, 100); } diff --git a/src/player-damage.c b/src/player-damage.c index 77d850d..05e2ac0 100644 --- a/src/player-damage.c +++ b/src/player-damage.c @@ -300,6 +300,11 @@ int inven_damage(inven_func typ, int perc) #ifdef JP if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON)) msg_print("やりやがったな!"); + else if ((p_ptr->pseikaku == SEIKAKU_CHARGEMAN)) + { + if (randint0(2) == 0) msg_print(_("ジュラル星人め!", "")); + else msg_print(_("弱い者いじめは止めるんだ!", "")); + } #endif /* Potions smash open */ diff --git a/src/trap.c b/src/trap.c index 9bb329f..5c93fdf 100644 --- a/src/trap.c +++ b/src/trap.c @@ -321,6 +321,9 @@ void hit_trap(bool break_trap) msg_print(_("落とし戸に落ちた!", "You have fallen through a trap door!")); if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (inventory[INVEN_BOW].name1 == ART_CRIMSON)) msg_print(_("くっそ~!", "")); + else if((p_ptr->pseikaku == SEIKAKU_CHARGEMAN)) + msg_print(_("ジュラル星人の仕業に違いない!", "")); +
まあこんな感じに。
モンスター誤認
個人的にキチガイアニメらしい着想を考えてみました。何でもかんでもとりあえずジュラル星人として襲い掛かるマジキチぶりをモンスターを誤認する能力で表してみようと思います。
具体的には地上では100%、地下でも20%の確率で相手をジュラル星人と思い込ませることにしましょう。この実装は、現状の「あやしい影」や「たぬき」で実装済のモンスターの実IDと外見IDの分化仕様から簡単にできました。
--- src/defines.h | 1 + src/monster2.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/defines.h b/src/defines.h index 4cf51fe..6955ce2 100644 --- a/src/defines.h +++ b/src/defines.h @@ -5119,6 +5119,7 @@ extern int PlayerUID; #define MON_WYRM_SPACE 1064 #define MON_JIZOTAKO 1065 #define MON_TANUKI 1067 +#define MON_ALIEN_JURAL 1082 #define MON_HATOPOPPO 1083 #define MON_KOGAN 1096 diff --git a/src/monster2.c b/src/monster2.c index 38a07a6..a6d0059 100644 --- a/src/monster2.c +++ b/src/monster2.c @@ -2904,10 +2904,14 @@ static bool monster_hook_tanuki(MONRACE_IDX r_idx) static IDX initial_r_appearance(MONRACE_IDX r_idx) { int attempts = 1000; - IDX ap_r_idx; DEPTH min = MIN(base_level-5, 50); + if (p_ptr->pseikaku == SEIKAKU_CHARGEMAN) + { + if (base_level == 0 || one_in_(5)) return MON_ALIEN_JURAL; + } + if (!(r_info[r_idx].flags7 & RF7_TANUKI)) return r_idx;
いやあ、絵になる頭のおかしさです。
最後に
いかがでしたでしょうか。これで参考になるならば是非色々いじってみてください。そんでもって、これを機に誰かソースコードのプルリクエストとかかましてくれませんかね……
ああ、ただ今後リファクタリングで修正を要する箇所が変化する可能性が……まあ分からんことがありましたらTwitterなどでご質問もどうぞ(震え声)
■ [魚類版深夜の真剣お絵描き60分一本勝負]アオダイ
2018/12/09
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part100…デバッグ時全角ファイル処理失敗の修正
どうせ何か仕出かしているんです(諦観)
https://osdn.net/projects/hengband/ticket/38791
- Sat Dec 8 18:53:51 2018 +0900: [Refactor] #37353 店処理のヘッダを externs.h から store.h へ分離。 Separate externs.h to store.h.
- Sat Dec 8 18:40:01 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Sat Dec 8 18:23:14 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Sat Dec 8 18:14:37 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Sat Dec 8 01:29:25 2018 +0900: [Refactor] #37353 メッセージとコメントの整理と型の置換 / Refactor messages and comments and type replacement.
- Sat Dec 8 01:10:55 2018 +0900: [Refactor] #37353 コメント整理と型の置換 / Refactor comments and type replacement.
- Sat Dec 8 01:02:25 2018 +0900: [Refactor] #37353 メッセージ整理と型の置換 / Refactor messages and type replacement.
2018/12/10
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part101…特別編「変愚蛮怒の種族実装例 ~MtGの主に青いヤクザ種族~(前編/遅刻した)」
はじめに
という訳でAdvent Calendar 10日目埋め、ついでに遅刻しました。ゆ る し て。
前回、新しい性格の実装(調整)をあっさり1日で済ませてしまいまして、そんじゃあ続けて次に簡単そうな種族でも行ってみようかという例を、前後編か前中後編くらいに分けてやっていこうと思います。
ファンタジーな種族が何だかんだ既にそろい踏みな中、足りない奴をD'ang旧ソースや、ニワカハマりしたMtGなどで探った結果、赤のゴブリン、緑のエルフに並ぶ、青の囲んで棒で叩くヤクザ種族、マーフォークで行ってみようと思います。
ちなみに私はレガシー2tで難題の予見者を出したり、現実を砕くもので暴力の限りを尽くしたり、終末を招くものでねっとりアド稼いだり、積み上げたマナ加速の果てにウラモグ兄貴を叩きつけると絶頂しそうになる変態糞エルドラージ使いなので、無色マナ塗れになりたい奴、至急メールくれや(自分語り)
性格より少々と面倒な種族実装
という訳で、まずさっさと性格の時同様、ハードコーディング上の基礎ステ設定から行ってみましょう。
まずdefines.hに新しくマーフォークのIDを定義し、種族最大数を増やします。
diff --git a/src/defines.h b/src/defines.h index ec8e7db..b6457ab 100644 --- a/src/defines.h +++ b/src/defines.h @@ -774,11 +774,12 @@ #define RACE_S_FAIRY 34 #define RACE_KUTAR 35 #define RACE_ANDROID 36 +#define RACE_MERFOLK 37 /* * Maximum number of player "race" types (see "table.c", etc) */ -#define MAX_RACES 37 +#define MAX_RACES 38
続けてプレイヤー種族のステータステーブル player_race race_info[MAX_RACES] にマーフォークのステータスを書き込みましょう。
--- a/src/tables.c +++ b/src/tables.c @@ -2768,6 +2768,22 @@ const player_race race_info[MAX_RACES] = 0, 0x0800001, }, + { +#ifdef JP + "マーフォーク", +#endif + "Merfolk", + + { -1, 0, 2, 1, -1, 1}, + 2, 3, 2, 1, 6, 11, -1, 5, + 10, 130, + 24, 16, + 66, 6, 130, 15, + 62, 6, 100, 10, + 2, + 0xE77E7FF, + }, + };
現状基本的ステータス以外はハーフエルフからのコピーです。追々調整します。player_raceの構造体は以下の通りです。
typedef struct player_race player_race; struct player_race { cptr title; /* Type of race */ #ifdef JP cptr E_title; /* 英語種族 */ #endif s16b r_adj[6]; /* Racial stat bonuses */ s16b r_dis; /* disarming */ s16b r_dev; /* magic devices */ s16b r_sav; /* saving throw */ s16b r_stl; /* stealth */ s16b r_srh; /* search ability */ s16b r_fos; /* search frequency */ s16b r_thn; /* combat (normal) */ s16b r_thb; /* combat (shooting) */ byte r_mhp; /* Race hit-dice modifier */ byte r_exp; /* Race experience factor */ byte b_age; /* base age */ byte m_age; /* mod age */ byte m_b_ht; /* base height (males) */ byte m_m_ht; /* mod height (males) */ byte m_b_wt; /* base weight (males) */ byte m_m_wt; /* mod weight (males) */ byte f_b_ht; /* base height (females) */ byte f_m_ht; /* mod height (females) */ byte f_b_wt; /* base weight (females) */ byte f_m_wt; /* mod weight (females) */ byte infra; /* Infra-vision range */ u32b choice; /* Legal class choices */ /* byte choice_xtra; */ };
Legal class choicesだけ分かりづらいかもしれませんが、要は職業選択時に種族に向いている職業、を戦士から順に指定しているビット配列です。現状ステータス上には何の影響もないものですね。
んでもって、birth.cに種族の解説メッセージを追加します。とりあえず完全に仕様を確定するまでは仮メッセージを加えます。
+"アンドロイドは機(略) + +"マーフォーク実装中", #else @@ -197,6 +199,8 @@ static cptr race_jouhou[MAX_RACES] = "An android is (略) +"Merfolk implementing.", + #endif };
ここまでは性格と全く同じ要領です。続けて、種族ごとに依存する項目として、生い立ちと、それに伴う社会的地位の変動設定などを加える必要がありますが、ひとまず今は一時人間と同じにしておきましょう。get_history()に以下のように加えます。
@@ -1277,6 +1281,7 @@ static void get_history(void) case RACE_HUMAN: case RACE_BARBARIAN: case RACE_DUNADAN: + case RACE_MERFOLK: { chart = 1; break; diff --git a/src/defines.h b/src/defines.h
ここまでで、一度は走らせてみようとするとこうなります。
これは「辺境の地」の町データをまとめている/lib/edit/t0000001.txtの以下の部分の問題です。
B:$0:N:The White Horse Inn:Otick:Human B:0:N:旅の宿『白馬亭』:オティック:人間 B:$0:A:0:Rest for the night:20:20:r:17:0 B:0:A:0:一泊する:20:20:r:17:0 B:$0:A:1:buy Food and drink:1:1:f:18:1 B:0:A:1:食事をする:1:1:f:18:1 B:$0:A:2:Listen for rumors:5:5:u:19:0 B:0:A:2:噂を聞く:5:5:u:19:0 B:$0:A:3:request Quest:0:0:q:6:0 B:0:A:3:クエスト:0:0:q:6:0 B:$0:A:4:Teleport to other town:500:500:m:42:0 B:0:A:4:他の町へ移動:500:500:m:42:0 B:$0:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0 B:0:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0
一番最後の行です。宿で、アンデッドやバルログなどが魔道具のエネルギーや血やら死体やらを売ってもらえない制限処理に該当する部分が、今回のマーフォークの追加に伴って、スロットが一つ増えたため、「引数不足」になってしまった次第です。このまま進めると恐ろしいバグで強制終了し、再起動しても町が消滅したりするというギャグみたいな状態になります。
ではこれを直していこうということで続きは次回。
2018/12/11
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part102…Visual Studio 2017ソリューション追加
ビルドで「warning C5045: /Qspectre スイッチが」の頻発を確認。
- http://techtarget.itmedia.co.jp/tt/news/1802/23/news01.html
- https://docs.microsoft.com/ja-jp/cpp/build/reference/qspectre?view=vs-2017
例のこれか。
全く個人的な話だが、Visual Studio 2015からカーソルが行端より先に行くと次の行でなく、一時的にスペースがつくやつ、不便な仕様かと思ったら、何かの拍子でエディタの「仮想空白文字を使用する」がONになっているだけだった。
2018/12/12
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part103…相変わらずリファクタリング中
いい加減機械的なこと以外にも手は付け始めていますが。
- Wed Dec 12 22:31:46 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Wed Dec 12 22:16:40 2018 +0900: [Refactor] #37353 メッセージ整理と型の置換 / Refactor messages and type replacement.
- Wed Dec 12 22:11:02 2018 +0900: [Refactor] #37353 Visual Studio 2017 の C4701警告潰し。/ Fix warning C4701 in Visual Studio 2017.
- Wed Dec 12 21:56:11 2018 +0900: [Refactor] #37353 mysqrt() を z-util.c へ移動。 / Move mysqrt() to z-util.c.
- Wed Dec 12 21:49:24 2018 +0900: [Fix] #37353 プロジェクトファイルとソース修正。 / Fix project file and sources.
- Wed Dec 12 21:45:23 2018 +0900: [Refactor] #37353 monster-hook を monsterrace-hook に改名。 / Rename monster-hook to monsterrace-hook.
- Wed Dec 12 21:33:50 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Wed Dec 12 21:28:49 2018 +0900: [Refactor] #37353 monster_living() の引数修正。 / Type replacement of monster_living()'s arguments.
- Wed Dec 12 20:56:26 2018 +0900: [Refactor] #37353 monster1~monster-hook間整理。 / Refactor between monster1 and monster-hook.
- Wed Dec 12 20:42:08 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Wed Dec 12 20:32:56 2018 +0900: [Refactor] #37353 Visual Studio 2017用プロジェクトの設定変更。 / Change configuration vcproj for Visual Studio 2017。
- Tue Dec 11 23:23:37 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Tue Dec 11 21:42:53 2018 +0900: [Refactor] #37353 Visual Studio 2017 ソリューション追加。 / Add solution of Visual Studio 2017.
2018/12/13
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part104…特別編「変愚蛮怒の種族実装例 ~MtGの主に青いヤクザ種族~(中編)」
Advent Calenderのネタのためにも、続けて実装していきます。
種族/職業/魔法領域制限指定のフォーマットを緩くする
前回のような種族の追加の毎に、参照しづらい/lib/edit内のデータをあれこれいじらないといけないのは、これからの追加上にも優しくないので、そこを修正しましょう。行の項目数が足りない時にはとりあえず埋めます。
同じ症状が職業、魔法領域でも発生するようなのでついでに直します。
--- src/init1.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/init1.c b/src/init1.c index 525dc16..4a57777 100644 --- a/src/init1.c +++ b/src/init1.c @@ -3838,11 +3838,13 @@ static errr parse_line_building(char *buf) /* Building Classes */ case 'C': { - if (tokenize(s + 2, MAX_CLASS, zz, 0) == MAX_CLASS) + int n; + n = tokenize(s + 2, MAX_CLASS, zz, 0); + if (n <= MAX_CLASS) { for (i = 0; i < MAX_CLASS; i++) - { - building[index].member_class[i] = (CLASS_IDX)atoi(zz[i]); + { + building[index].member_class[i] = ((i > n) ? (CLASS_IDX)atoi(zz[i]) : 1); } break; @@ -3854,11 +3856,13 @@ static errr parse_line_building(char *buf) /* Building Races */ case 'R': { - if (tokenize(s+2, MAX_RACES, zz, 0) == MAX_RACES) + int n; + n = tokenize(s + 2, MAX_RACES, zz, 0); + if (n <= MAX_RACES) { for (i = 0; i < MAX_RACES; i++) { - building[index].member_race[i] = (RACE_IDX)atoi(zz[i]); + building[index].member_race[i] = ((i > n) ? (RACE_IDX)atoi(zz[i]) : 1); } break; @@ -3870,11 +3874,13 @@ static errr parse_line_building(char *buf) /* Building Realms */ case 'M': { - if (tokenize(s+2, MAX_MAGIC, zz, 0) == MAX_MAGIC) + int n; + n = tokenize(s + 2, MAX_MAGIC, zz, 0); + if (n <= MAX_MAGIC) { for (i = 0; i < MAX_MAGIC; i++) { - building[index].member_realm[i+1] = (REALM_IDX)atoi(zz[i]); + building[index].member_realm[i+1] = ((i > n) ? (REALM_IDX)atoi(zz[i]) : 1); } break; --
2019/02/04追記・ここ不等号逆でした。長いこと気づかず大変申し訳ない。 今はこうなっています。
/* Building Classes */ case 'C': { int n; n = tokenize(s + 2, MAX_CLASS, zz, 0); for (i = 0; i < MAX_CLASS; i++) { building[index].member_class[i] = ((i < n) ? (CLASS_IDX)atoi(zz[i]) : 1); } break; } /* Building Races */ case 'R': { int n; n = tokenize(s + 2, MAX_RACES, zz, 0); for (i = 0; i < MAX_RACES; i++) { building[index].member_race[i] = ((i < n) ? (RACE_IDX)atoi(zz[i]) : 1); } break; } /* Building Realms */ case 'M': { int n; n = tokenize(s + 2, MAX_MAGIC, zz, 0); for (i = 0; i < MAX_MAGIC; i++) { building[index].member_realm[i+1] = ((i < n) ? (REALM_IDX)atoi(zz[i]) : 1); } break; }
その上で、マーフォークの指定を行う。
基本、人間とエルフあたりと同じ食糧やその他事情で済むでしょうから適当に。
diff --git a/lib/edit/t0000001.txt b/lib/edit/t0000001.txt index f2082c9..85ce876 100644 --- a/lib/edit/t0000001.txt +++ b/lib/edit/t0000001.txt @@ -496,8 +496,8 @@ B:$0:A:3:request Quest:0:0:q:6:0 B:0:A:3:クエスト:0:0:q:6:0 B:$0:A:4:Teleport to other town:500:500:m:42:0 B:0:A:4:他の町へ移動:500:500:m:42:0 -B:$0:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0 -B:0:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0 +B:$0:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0:1 +B:0:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0:1 B:$1:N:Mayor:Uldrik:Human B:1:N:村長:ウルドリック:人間 diff --git a/lib/edit/t0000002.txt b/lib/edit/t0000002.txt index da73aa1..8e50b02 100644 --- a/lib/edit/t0000002.txt +++ b/lib/edit/t0000002.txt @@ -321,8 +321,8 @@ B:$4:A:2:Listen for rumors:10:10:u:19:0 B:4:A:2:噂を聞く:10:10:u:19:0 B:$4:A:3:Teleport to other town:500:500:m:42:0 B:4:A:3:他の町へ移動:500:500:m:42:0 -B:$4:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0 -B:4:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0 +B:$4:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0:1 +B:4:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0:1 B:$5:N:Beastmaster:Lorien:Elf B:5:N:モンスター仙人:ロリエン:エルフ diff --git a/lib/edit/t0000003.txt b/lib/edit/t0000003.txt index b0609b0..7973022 100644 --- a/lib/edit/t0000003.txt +++ b/lib/edit/t0000003.txt @@ -264,8 +264,8 @@ B:$4:A:2:Listen for rumors:10:10:u:19:0 B:4:A:2:噂を聞く:10:10:u:19:0 B:$4:A:3:Teleport to other town:500:500:m:42:0 B:4:A:3:他の町へ移動:500:500:m:42:0 -B:$4:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0 -B:4:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0 +B:$4:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0:1 +B:4:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0:1 B:$5:N:Beastmaster:Draxle:Draconian B:5:N:モンスター仙人:ドラクスル:ドラコニアン diff --git a/lib/edit/t0000004.txt b/lib/edit/t0000004.txt index 7850a3f..30cd5c6 100644 --- a/lib/edit/t0000004.txt +++ b/lib/edit/t0000004.txt @@ -171,8 +171,8 @@ B:$4:A:2:Listen for rumors:10:10:u:19:0 B:4:A:2:噂を聞く:10:10:u:19:0 B:$4:A:3:Teleport to other town:500:500:m:42:0 B:4:A:3:他の町へ移動:500:500:m:42:0 -B:$4:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0 -B:4:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0 +B:$4:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0:1 +B:4:R:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0:1 B:$5:N:Beastmaster:Aradreth:Elf B:5:N:モンスター仙人:アラドレス:エルフ @@ -252,8 +252,8 @@ B:$13:A:0:Recall to dungeon:0:150:r:33:0 B:13:A:0:ダンジョンへ帰還:0:150:r:33:0 B:$13:A:1:Teleport to dungeon-level:100000:1000000:t:34:0 B:13:A:1:階を指定してテレポート:100000:1000000:t:34:0 -B:$13:R:0:0:0:0:0:0:0:0:1:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 -B:13:R:0:0:0:0:0:0:0:0:1:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 +B:$13:R:0:0:0:0:0:0:0:0:1:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 +B:13:R:0:0:0:0:0:0:0:0:1:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 B:$13:M:0:0:0:0:0:2:0:0:0:0 B:13:M:0:0:0:0:0:2:0:0:0:0 diff --git a/lib/edit/t0000005.txt b/lib/edit/t0000005.txt index f64b4bb..6bf5f6f 100644 --- a/lib/edit/t0000005.txt +++ b/lib/edit/t0000005.txt @@ -128,8 +128,8 @@ B:$4:A:1:Buy food and drink:2:2:f:18:1 B:4:A:1:食事をする:2:2:f:18:1 B:$4:A:2:Listen for rumors:10:10:u:19:0 B:4:A:2:噂を聞く:10:10:u:19:0 -B:$4:R:2:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0 -B:4:R:2:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0 +B:$4:R:2:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0:1 +B:4:R:2:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:0:0:0:0:0:1:1:0:1:0:1:1:1:0:1 B:$4:A:3:Identify item:100:100:i:44:0 B:4:A:3:アイテム鑑定:100:100:i:44:0 @@ -152,8 +152,8 @@ B:$14:A:0:Request quest:0:0:q:6:1 B:14:A:0:クエスト:0:0:q:6:1 B:$14:A:1:Cure mutation:1000:5000:m:35:0 B:14:A:1:突然変異を治療する:1000:5000:m:35:0 -B:$14:R:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:1:0:0:0:0:0:0:0 -B:14:R:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:1:0:0:0:0:0:0:0 +B:$14:R:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:1:0:0:0:0:0:0:0:0 +B:14:R:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:1:0:0:0:0:0:0:0:0 B:$14:M:0:0:0:2:0:0:0:0:0:0 B:14:M:0:0:0:2:0:0:0:0:0:0
その際に配列オーバーのバグも修正しました。
--- a/src/init1.c +++ b/src/init1.c @@ -3752,7 +3752,7 @@ static errr parse_line_feature(char *buf) static errr parse_line_building(char *buf) { int i; - char *zz[37]; + char *zz[1000]; int index; char *s;
水流耐性を新しく実装してみる
さて、マーフォークとしての独自の仕様として、やはり水棲種族なのですから、レアな水流耐性など持っていても良いかもしれません。現状として仕様がないので、ここで新しく水流耐性を追加してみます。
まず新しくplayer_type構造体にresist_waterを加えて、calc_nonuses()に初期化を追加、種族がマーフォークならばTRUEにします。
--- a/src/types.h +++ b/src/types.h @@ -1248,6 +1248,7 @@ struct player_type bool resist_neth; /* Resist nether */ bool resist_fear; /* Resist fear */ bool resist_time; /* Resist time */ + bool resist_water; /* Resist water */ bool reflect; /* Reflect 'bolt' attacks */ bool sh_fire; /* Fiery 'immolation' effect */
--- a/src/xtra1.c +++ b/src/xtra1.c @@ -3290,6 +3290,7 @@ void calc_bonuses(void) p_ptr->resist_blind = FALSE; p_ptr->resist_neth = FALSE; p_ptr->resist_time = FALSE; + p_ptr->resist_water = FALSE; p_ptr->resist_fear = FALSE; p_ptr->reflect = FALSE; p_ptr->sh_fire = FALSE; @@ -3770,6 +3771,8 @@ void calc_bonuses(void) p_ptr->resist_pois = TRUE; p_ptr->hold_exp = TRUE; break; + case RACE_MERFOLK: + p_ptr->resist_water = TRUE; default: /* Do nothing */ ;
そしてこの水流耐性がある場合、GF_WATERのダメージを喰らった時、轟音や混乱耐性とは別に朦朧や混乱に陥らず、ダメージが1/4になるようにしましょう。
diff --git a/src/spells1.c b/src/spells1.c index b0f8750..b10d18b 100644 --- a/src/spells1.c +++ b/src/spells1.c @@ -5412,19 +5412,21 @@ static bool project_p(MONSTER_IDX who, cptr who_name, int r, POSITION y, POSITIO if (fuzzy) msg_print(_("何か湿ったもので攻撃された!", "You are hit by something wet!")); if (!CHECK_MULTISHADOW()) { - if (!p_ptr->resist_sound) + if (!p_ptr->resist_sound && !p_ptr->resist_water) { set_stun(p_ptr->stun + randint1(40)); } - if (!p_ptr->resist_conf) + if (!p_ptr->resist_conf && !p_ptr->resist_water) { set_confused(p_ptr->confused + randint1(5) + 5); } - if (one_in_(5)) + if (one_in_(5) && !p_ptr->resist_water) { inven_damage(set_cold_destroy, 3); } + + if (p_ptr->resist_water) get_damage /= 4; }
ついでに重量オーバーでも溺れなくなります。
--- a/src/dungeon.c +++ b/src/dungeon.c @@ -1505,7 +1505,7 @@ static void process_world_aux_hp_and_sp(void) } if (have_flag(f_ptr->flags, FF_WATER) && have_flag(f_ptr->flags, FF_DEEP) && - !p_ptr->levitation && !p_ptr->can_swim) + !p_ptr->levitation && !p_ptr->can_swim && !p_ptr->res_water) { if (p_ptr->total_weight > weight_limit()) {
大分それらしくなってきたと思います。このまま間延びですが後編へ。
2018/12/14
■ [魚類版深夜の真剣お絵描き60分一本勝負]ウキクサウオ
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part105…リファクタリング、ベースアイテムコールバック分離
まだまだファイル名と関数が一致しない関係は多く。
- Sat Dec 15 02:18:07 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Sat Dec 15 02:12:02 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Sat Dec 15 02:09:26 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Sat Dec 15 02:05:13 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Sat Dec 15 02:00:11 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Sat Dec 15 01:51:36 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Sat Dec 15 00:26:14 2018 +0900: [Refactor] #37353 ベースアイテム判定処理を objectkind-hook.c/h へ分離。 Separate judgment base-item functions to objectkind-hook.c/h.
- Fri Dec 14 22:47:52 2018 +0900: [Refactor] #37353 メッセージ整理と型の置換 / Refactor messages and type replacement.
- Fri Dec 14 01:05:27 2018 +0900: [Fix] #37353 コメントミス修正 / Fix comments.
2018/12/15
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part106…特別編「変愚蛮怒の種族実装例 ~MtGの主に青いヤクザ種族~(後編)」
前回から続けていきます。
水地形にいるか否か、浮遊しているかどうかで加速したり減速したりする。
MtGのマーフォークは各次元(ともすれば絵師)によって下半身が魚や水蛇っぽかったり、二本脚であったり、それを時々に応じて変化させたり様々なようですが、総じて水中での機動に長けていて、陸上でも活動はできるが限度があるようです。
それに即して以下のようなルールを考えます。
- 水地形(FF_WATERフラグ付き)の地形に入っている間は2+(レベル)/10の加速がつく。
- それ以外の地形で浮遊を持っていない場合、加速-2。
これを実装するために、move_player_effect()の地形参照処理を直した上で、移動前と移動後の水地形の是非が切り替わる毎にプレイヤーの修正更新処理を呼び出すよう追加します。丁度前後には忍者の超隠密や早駆けの切替処理があります。
diff --git a/src/cmd1.c b/src/cmd1.c index 5efc9be..c78e626 100644 --- a/src/cmd1.c +++ b/src/cmd1.c @@ -826,16 +826,17 @@ bool player_can_enter(s16b feature, u16b mode) */ bool move_player_effect(POSITION ny, POSITION nx, BIT_FLAGS mpe_mode) { + POSITION oy = p_ptr->y; + POSITION ox = p_ptr->x; cave_type *c_ptr = &cave[ny][nx]; + cave_type *oc_ptr = &cave[oy][ox]; feature_type *f_ptr = &f_info[c_ptr->feat]; + feature_type *of_ptr = &f_info[oc_ptr->feat]; if (!(mpe_mode & MPE_STAYING)) { - POSITION oy = p_ptr->y; - POSITION ox = p_ptr->x; - cave_type *oc_ptr = &cave[oy][ox]; - IDX om_idx = oc_ptr->m_idx; - IDX nm_idx = c_ptr->m_idx; + MONSTER_IDX om_idx = oc_ptr->m_idx; + MONSTER_IDX nm_idx = c_ptr->m_idx; /* Move the player */ p_ptr->y = ny; @@ -885,7 +886,6 @@ bool move_player_effect(POSITION ny, POSITION nx, BIT_FLAGS mpe_mode) } p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE | PU_DISTANCE); - p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON); /* Remove "unsafe" flag */ @@ -908,6 +908,15 @@ bool move_player_effect(POSITION ny, POSITION nx, BIT_FLAGS mpe_mode) msg_print(_("ここでは素早く動けない。", "You cannot run in here.")); set_action(ACTION_NONE); } + + if (p_ptr->prace == RACE_MERFOLK) + { + if(have_flag(f_ptr->flags, FF_WATER) ^ have_flag(of_ptr->flags, FF_WATER)) + { + p_ptr->update |= PU_BONUS; + update_stuff(); + } + } } if (mpe_mode & MPE_ENERGY_USE)
calc_bonuses()の種族特性switch文に以下のように条件を追加します。
@@ -3773,6 +3776,15 @@ void calc_bonuses(void) break; case RACE_MERFOLK: p_ptr->resist_water = TRUE; + if(have_flag(f_ptr->flags, FF_WATER)) + { + new_speed += (2 + p_ptr->lev / 10); + } + else if(!p_ptr->levitation) + { + new_speed -= 2; + } + break; default: /* Do nothing */ ;
おまけに浮遊の指輪を装備させる。
この実装を済ませた上で、ちょっと戦士で盗賊クエに行ったのですがちょっと参りました。最序盤の減速-2はかなり大きく、追い剥ぎとやり合ってギリで負けています。実際-2は通常の0.8倍になってしまうのですから厳しいかも知れません。
減速を-1としてもいいですが、そもそも自力救済が求められるような世界で、従来水棲の種族が地上で長く滞在する以上は、魔法の装備で問題を軽減するのも当然かも知れません。
浮遊の指輪自体は最序盤のアイテムにして、早々に装備枠を逼迫させる要因になる程度のものですし、種族マーフォークを選んでいる場合は常に浮遊の指輪を与えることにしましょう。
birth.cにplayer_outfit()への追加を行います。
diff --git a/src/birth.c b/src/birth.c index 142896f..ad99a51 100644 --- a/src/birth.c +++ b/src/birth.c @@ -2393,6 +2393,13 @@ void player_outfit(void) } q_ptr = &forge; + if (p_ptr->prace == RACE_MERFOLK) + { + object_prep(q_ptr, lookup_kind(TV_RING, SV_RING_LEVITATION_FALL)); + q_ptr->number = 1; + add_outfit(q_ptr); + } + if ((p_ptr->pclass == CLASS_RANGER) || (p_ptr->pclass == CLASS_CAVALRY)) { /* Hack -- Give the player some arrows */
calc_bonuses()のミスを修正
ここまでで浮遊の指輪を自動装備させて気づきました。calc_bonuses()内の処理で装備による浮遊がTRUEになる前から、マーフォークの減速判定を行っているため、適用がされていません。プレイヤー自身の耐性や能力などに関わる処理はcalc_bonuses()の後半に回しましょう。
--- src/xtra1.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/xtra1.c b/src/xtra1.c index 2065f39..40cd5bf 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -3776,14 +3776,6 @@ void calc_bonuses(void) break; case RACE_MERFOLK: p_ptr->resist_water = TRUE; - if(have_flag(f_ptr->flags, FF_WATER)) - { - new_speed += (2 + p_ptr->lev / 10); - } - else if(!p_ptr->levitation) - { - new_speed -= 2; - } break; default: /* Do nothing */ @@ -4898,6 +4890,20 @@ void calc_bonuses(void) /* Searching slows the player down */ if (p_ptr->action == ACTION_SEARCH) new_speed -= 10; + /* Feature bonus */ + if(p_ptr->prace == RACE_MERFOLK) + { + if (have_flag(f_ptr->flags, FF_WATER)) + { + new_speed += (2 + p_ptr->lev / 10); + } + else if (!p_ptr->levitation) + { + new_speed -= 2; + } + } + + /* Actual Modifier Bonuses (Un-inflate stat bonuses) */ p_ptr->to_a += ((int)(adj_dex_ta[p_ptr->stat_ind[A_DEX]]) - 128); p_ptr->to_d[0] += ((int)(adj_str_td[p_ptr->stat_ind[A_STR]]) - 128);
大体できました
この位まで実装すれば、種族としての特化は十分にできたと思います。まだ、生い立ち設定、援軍指定とか本当に正式に詰めることは、細々とありますが、一旦ここで完結とさせてもらおうと思います。
正式なアップは2.2.2として調整済ませて出します。お楽しみに。
2019/02/14 追記 マーフォーク用の rgold_adj を追加
忘れていました(小声)rgold_adjは店の主との種族的相性補正を与える者です。ないと色々まずいのになぜ今まで動いていたのか。
ともかく面倒ですが必ず入れましょう。
2018/12/17
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part107…特別編「変愚蛮怒の技能実装例 ~剣は捨てても盾は捨てるなという名ゼリフを知らないのかよ~」
Roguelike Advent Calendar 2018の17日目です。肩こりと眠気でまた遅刻しました。ゆ る し て。
今回もしつこく記事のためという不純な動機で新しく盾技能などを追加してみようと思います。例によってブランチを切って調整などは済ませてから正規実装予定です。
盾技能の枠を追加する。
現在実装されている技能枠はマーシャルアーツ、乗馬、二刀流の三種。実装当初から配列上10枠用意してくれているため面倒になるセーブデータ処理の追加は行わずに済みそうです。
ただ、マジックナンバーはやめろください。ということで直しながら以下のように。
diff --git a/src/cmd4.c b/src/cmd4.c index c698567..63afa94 100644 --- a/src/cmd4.c +++ b/src/cmd4.c @@ -5787,9 +5787,13 @@ static void do_cmd_knowledge_skill_exp(void) FILE *fff; char file_name[1024]; - char skill_name[3][20]={_("マーシャルアーツ", "Martial Arts "), - _("二刀流 ", "Dual Wielding "), - _("乗馬 ", "Riding ")}; + char skill_name[GINOU_TEMPMAX][20] = + { + _("マーシャルアーツ", "Martial Arts "), + _("二刀流 ", "Dual Wielding "), + _("乗馬 ", "Riding "), + _("盾 ", "Shield ") + }; /* Open a new file */ fff = my_fopen_temp(file_name, 1024); @@ -5799,7 +5803,7 @@ static void do_cmd_knowledge_skill_exp(void) return; } - for (i = 0; i < 3; i++) + for (i = 0; i < GINOU_TEMPMAX; i++) { skill_exp = p_ptr->skill_exp[i]; fprintf(fff, "%-20s ", skill_name[i]); diff --git a/src/defines.h b/src/defines.h index ec8e7db..06d5052 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4661,6 +4661,8 @@ extern int PlayerUID; #define GINOU_SUDE 0 #define GINOU_NITOURYU 1 #define GINOU_RIDING 2 +#define GINOU_SHIELD 3 +#define GINOU_TEMPMAX 4 #define GINOU_MAX 10
s_info.txtに各職業ごとの初期値、最大値を指定する
上記の通り今のままではどんな職業でも初期値最大値が0なので、s_info.txtに新しく追加してやる必要があります。
長いのでdiff張りつけは略します。各職業ごとに追加。全く無関係な話ですが武器経験値は似たような武器であれこれ付けすぎて冗長な気はします。
盾技能上昇処理追加
盾を装備している時に、相手の攻撃をかわすことに成功した際に追加。
現状は惰性で他の技能値とほぼ似たような上昇条件です。
src/melee1.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/melee1.c b/src/melee1.c index 1406cac..e10c385 100644 --- a/src/melee1.c +++ b/src/melee1.c @@ -1455,8 +1455,8 @@ bool py_attack(POSITION y, POSITION x, BIT_FLAGS mode) if (cur < max) { - int ridinglevel = r_info[m_list[p_ptr->riding].r_idx].level; - int targetlevel = r_ptr->level; + DEPTH ridinglevel = r_info[m_list[p_ptr->riding].r_idx].level; + DEPTH targetlevel = r_ptr->level; int inc = 0; if ((cur / 200 - 5) < targetlevel) @@ -1472,7 +1472,6 @@ bool py_attack(POSITION y, POSITION x, BIT_FLAGS mode) } p_ptr->skill_exp[GINOU_RIDING] = MIN(max, cur + inc); - p_ptr->update |= (PU_BONUS); } } @@ -3224,6 +3223,33 @@ bool make_attack_normal(MONSTER_IDX m_idx) #endif } + + /* Gain shield experience */ + if (object_is_armour(&inventory[INVEN_RARM]) || object_is_armour(&inventory[INVEN_LARM])) + { + int cur = p_ptr->skill_exp[GINOU_SHIELD]; + int max = s_info[p_ptr->pclass].s_max[GINOU_SHIELD]; + + if (cur < max) + { + DEPTH targetlevel = r_ptr->level; + int inc = 0; + + + /* Extra experience */ + if ((cur / 100) < targetlevel) + { + if ((cur / 100 + 15) < targetlevel) + inc += 1 + (targetlevel - (cur / 100 + 15)); + else + inc += 1; + } + + p_ptr->skill_exp[GINOU_SHIELD] = MIN(max, cur + inc); + p_ptr->update |= (PU_BONUS); + } + } + damage = 0; break;
盾技能によるAC修正追加
例によってデカいcalc_bonuses()内にぽつりと。追加ACが最大+12は小さいか大きいか、正式実装までには調整したいと思います。
diff --git a/src/xtra1.c b/src/xtra1.c index 3795201..3a84445 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -4355,6 +4355,13 @@ void calc_bonuses(void) } } + /* Shield skill bonus */ + if (object_is_armour(&inventory[INVEN_RARM]) || object_is_armour(&inventory[INVEN_LARM])) + { + p_ptr->ac += p_ptr->skill_exp[GINOU_SHIELD] * (1 + p_ptr->lev / 22) / 2000; + p_ptr->dis_ac += p_ptr->skill_exp[GINOU_SHIELD] * (1 + p_ptr->lev / 22) / 2000; + } + if (old_mighty_throw != p_ptr->mighty_throw) { /* Redraw average damege display of Shuriken */
技能値8000でレベル6ならば+4修正。2(耐久修正)+3(盾AC)+14(鎧AC)+4=23で計算通り。
こんなんなりました。以上!終わり!閉廷!
2018/12/18
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part108…更新処理整理
どうせ、handle_stuff()でまとめているなら半端にするなよということで。
- Tue Dec 18 22:37:03 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Tue Dec 18 22:28:27 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Tue Dec 18 22:22:38 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Tue Dec 18 22:14:57 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Tue Dec 18 22:03:25 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Tue Dec 18 22:01:21 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Tue Dec 18 21:55:36 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Tue Dec 18 21:41:13 2018 +0900: [Refactor] #37353 ソース整理 / Refactor sources.
- Sun Dec 16 11:22:40 2018 +0900: [Refactor] #37353 関数スコープ整理。 / Adjust scope of functions.
- Sun Dec 16 11:14:07 2018 +0900: [Refactor] #37353 notice_stuff() の直接呼出しを抑止。 / Forbid call of notice_stuff() except handle_stuff().
- Sun Dec 16 11:05:38 2018 +0900: [Refactor] #37353 window_stuff() の直接呼出しを抑止。 / Forbid call of window_stuff() except handle_stuff().
- Sun Dec 16 10:56:32 2018 +0900: [Refactor] #37353 redraw_stuff() の直接呼出しを抑止。 / Forbid call of redraw_stuff() except handle_stuff().
- Sun Dec 16 10:49:24 2018 +0900: [Refactor] #37353 update_stuff() の直接呼出しを抑止。 / Forbid call of update_stuff() except handle_stuff().
- Sun Dec 16 10:33:23 2018 +0900: [Refactor] #37353 calc_bonuses の直接呼出しを抑止。 / Forbid call of calc_bonuses() except handle_stuff().
- Sun Dec 16 10:13:51 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Sun Dec 16 10:02:51 2018 +0900: [Refactor] #37353 kind_is_potion() を objectkind-hook.c に移動。
2018/12/19
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part109…特別編「変愚蛮怒の地形実装例 ~毒沼やら酸の沼やら~(前編)」
今日の枠が埋まりそうになかったのでしつこくやっていきます。今回の地形追加は、以前から少しだけ手を付けてみた内容であったりします。
現状ダメージ地形は溶岩と、浮遊なし&重量オーバー時の溺れ効果しかないので、折角だからもっと属性ダメージフィールドを増やしてみようという魂胆です。
FF_*定義
まずがf_info.txtで用いる地形フラグであるFF_*を新しく定義してみましょう。
例によってdefines.hへの追加と
diff --git a/src/defines.h b/src/defines.h index 1cf2681..21b2982 100644 --- a/src/defines.h +++ b/src/defines.h @@ -988,15 +988,15 @@ #define FF_LAVA 40 #define FF_SHALLOW 41 #define FF_DEEP 42 -/* #define FF_FILLED 43 */ +#define FF_POISON_PUDDLE 43 #define FF_HURT_ROCK 44 /* #define FF_HURT_FIRE 45 */ /* #define FF_HURT_COLD 46 */ /* #define FF_HURT_ACID 47 */ -/* #define FF_ICE 48 */ -/* #define FF_ACID 49 */ -/* #define FF_OIL 50 */ -/* #define FF_XXX04 51 */ +#define FF_COLD_PUDDLE 48 +#define FF_ACID_PUDDLE 49 +/* #define FF_OIL 50 +#define FF_ELEC_PUDDLE 51 /* #define FF_CAN_CLIMB 52 */ #define FF_CAN_FLY 53 #define FF_CAN_SWIM 54
f_info.txtで用いるフラグ文字列の追加です。こうして見てみると結構没になっていたらしい種々の地形フラグの形跡はあるようです。
diff --git a/src/init1.c b/src/init1.c index 4e70c73..c98898f 100644 --- a/src/init1.c +++ b/src/init1.c @@ -189,15 +189,15 @@ static cptr f_info_flags[] = "LAVA", "SHALLOW", "DEEP", - "FILLED", + "POISON_PUDDLE", "HURT_ROCK", "HURT_FIRE", "HURT_COLD", "HURT_ACID", - "ICE", - "ACID", + "COLD_PUDDLE", + "ACID_PUDDLE", "OIL", - "XXX04", + "ELEC_PUDDLE", "CAN_CLIMB", "CAN_FLY", "CAN_SWIM",
地形ダメージ処理実装
dungeon.cの溶岩の熱処理を実装している場所に、そのまま参考にしつつ冷気、電撃、酸、毒ダメージの実装をしてみます。表現や対応する英文はちと苦しいかもしれません。
--- a/src/dungeon.c +++ b/src/dungeon.c @@ -1502,6 +1502,160 @@ static void process_world_aux_hp_and_sp(void) } } + if (have_flag(f_ptr->flags, FF_COLD_PUDDLE) && !IS_INVULN() && !p_ptr->immune_cold) + { + int damage = 0; + + if (have_flag(f_ptr->flags, FF_DEEP)) + { + damage = 6000 + randint0(4000); + } + else if (!p_ptr->levitation) + { + damage = 3000 + randint0(2000); + } + + if (damage) + { + if (p_ptr->resist_cold) damage = damage / 3; + if (IS_OPPOSE_COLD()) damage = damage / 3; + if (p_ptr->levitation) damage = damage / 5; + + damage = damage / 100 + (randint0(100) < (damage % 100)); + + if (p_ptr->levitation) + { + msg_print(_("冷気に覆われた!", "The cold engulfs you!")); + take_hit(DAMAGE_NOESCAPE, damage, format(_("%sの上に浮遊したダメージ", "flying over %s"), + f_name + f_info[get_feat_mimic(&cave[p_ptr->y][p_ptr->x])].name), -1); + } + else + { + cptr name = f_name + f_info[get_feat_mimic(&cave[p_ptr->y][p_ptr->x])].name; + msg_format(_("%sに凍えた!", "The %s frostbites you!"), name); + take_hit(DAMAGE_NOESCAPE, damage, name, -1); + } + + cave_no_regen = TRUE; + } + } + + if (have_flag(f_ptr->flags, FF_ELEC_PUDDLE) && !IS_INVULN() && !p_ptr->immune_elec) + { + int damage = 0; + + if (have_flag(f_ptr->flags, FF_DEEP)) + { + damage = 6000 + randint0(4000); + } + else if (!p_ptr->levitation) + { + damage = 3000 + randint0(2000); + } + + if (damage) + { + if (p_ptr->resist_elec) damage = damage / 3; + if (IS_OPPOSE_ELEC()) damage = damage / 3; + if (p_ptr->levitation) damage = damage / 5; + + damage = damage / 100 + (randint0(100) < (damage % 100)); + + if (p_ptr->levitation) + { + msg_print(_("電撃を受けた!", "The electric shocks you!")); + take_hit(DAMAGE_NOESCAPE, damage, format(_("%sの上に浮遊したダメージ", "flying over %s"), + f_name + f_info[get_feat_mimic(&cave[p_ptr->y][p_ptr->x])].name), -1); + } + else + { + cptr name = f_name + f_info[get_feat_mimic(&cave[p_ptr->y][p_ptr->x])].name; + msg_format(_("%sに感電した!", "The %s shocks you!"), name); + take_hit(DAMAGE_NOESCAPE, damage, name, -1); + } + + cave_no_regen = TRUE; + } + } + + if (have_flag(f_ptr->flags, FF_ACID_PUDDLE) && !IS_INVULN() && !p_ptr->immune_acid) + { + int damage = 0; + + if (have_flag(f_ptr->flags, FF_DEEP)) + { + damage = 6000 + randint0(4000); + } + else if (!p_ptr->levitation) + { + damage = 3000 + randint0(2000); + } + + if (damage) + { + if (p_ptr->resist_acid) damage = damage / 3; + if (IS_OPPOSE_ACID()) damage = damage / 3; + if (p_ptr->levitation) damage = damage / 5; + + damage = damage / 100 + (randint0(100) < (damage % 100)); + + if (p_ptr->levitation) + { + msg_print(_("酸を受けた!", "The acid melt you!")); + take_hit(DAMAGE_NOESCAPE, damage, format(_("%sの上に浮遊したダメージ", "flying over %s"), + f_name + f_info[get_feat_mimic(&cave[p_ptr->y][p_ptr->x])].name), -1); + } + else + { + cptr name = f_name + f_info[get_feat_mimic(&cave[p_ptr->y][p_ptr->x])].name; + msg_format(_("%sに溶かされた!", "The %s melts you!"), name); + take_hit(DAMAGE_NOESCAPE, damage, name, -1); + } + + cave_no_regen = TRUE; + } + } + + if (have_flag(f_ptr->flags, FF_POISON_PUDDLE) && !IS_INVULN()) + { + int damage = 0; + + if (have_flag(f_ptr->flags, FF_DEEP)) + { + damage = 6000 + randint0(4000); + } + else if (!p_ptr->levitation) + { + damage = 3000 + randint0(2000); + } + + if (damage) + { + if (p_ptr->resist_pois) damage = damage / 3; + if (IS_OPPOSE_POIS()) damage = damage / 3; + if (p_ptr->levitation) damage = damage / 5; + + damage = damage / 100 + (randint0(100) < (damage % 100)); + + if (p_ptr->levitation) + { + msg_print(_("毒気を吸い込んだ!", "The gas poisons you!")); + take_hit(DAMAGE_NOESCAPE, damage, format(_("%sの上に浮遊したダメージ", "flying over %s"), + f_name + f_info[get_feat_mimic(&cave[p_ptr->y][p_ptr->x])].name), -1); + if (p_ptr->resist_pois) (void)set_poisoned(p_ptr->poisoned + 1); + } + else + { + cptr name = f_name + f_info[get_feat_mimic(&cave[p_ptr->y][p_ptr->x])].name; + msg_format(_("%sに毒された!", "The %s poisons you!"), name); + take_hit(DAMAGE_NOESCAPE, damage, name, -1); + if (p_ptr->resist_pois) (void)set_poisoned(p_ptr->poisoned + 3); + } + + cave_no_regen = TRUE; + } + } + if (have_flag(f_ptr->flags, FF_WATER) && have_flag(f_ptr->flags, FF_DEEP) && !p_ptr->levitation && !p_ptr->can_swim) {
f_info.txtに各FF_*を当てた新地形を追加。
同じく、これも地形名とかもう少しスマートな表現はあっていい気はします。多少前述のルールの変更も含めて。
--- a/lib/edit/f_info.txt +++ b/lib/edit/f_info.txt @@ -1796,3 +1796,67 @@ W:2 K:DESTROYED:SHALLOW_WATER F:POWER_40 | LOS | REMEMBER | TUNNEL | WALL | HURT_ROCK | CAN_PASS | F:HURT_DISI | GLASS + +N:227:HEAVY_COLD_ZONE +J:極低温帯 +E:heavy cold zone +G:~:W +W:2 +F:LOS | PROJECT | MOVE | PLACE | REMEMBER | GLOW | COLD_PUDDLE | DEEP | CAN_FLY | +F:TELEPORTABLE + +N:228:COLD_ZONE +J:低温帯 +E:cold zone +G:~:w +W:2 +F:LOS | PROJECT | MOVE | PLACE | DROP | REMEMBER | COLD_PUDDLE | SHALLOW | CAN_FLY | +F:TELEPORTABLE + +N:229:HEAVY_ELECTRICAL_ZONE +J:高圧帯電帯 +E:heavy electrical zone +G:~:y +W:2 +F:LOS | PROJECT | MOVE | PLACE | REMEMBER | GLOW | ELEC_PUDDLE | DEEP | CAN_FLY | +F:TELEPORTABLE + +N:230:ELECTRICAL_ZONE +J:帯電帯 +E:electrical zone +G:~:o +W:2 +F:LOS | PROJECT | MOVE | PLACE | DROP | REMEMBER | ELEC_PUDDLE | SHALLOW | CAN_FLY | +F:TELEPORTABLE + +N:231:DEEP_ACID_PUDDLE +J:深い酸の沼 +E:deep acid puddle +G:~:u +W:2 +F:LOS | PROJECT | MOVE | PLACE | REMEMBER | GLOW | ACID_PUDDLE | DEEP | CAN_FLY | +F:TELEPORTABLE + +N:232:SHALLOW_ACID_PUDDLE +J:浅い酸の沼 +E:shallow acid puddle +G:~:U +W:2 +F:LOS | PROJECT | MOVE | PLACE | DROP | REMEMBER | ACID_PUDDLE | SHALLOW | CAN_FLY | +F:TELEPORTABLE + +N:233:DEEP_POISONOUS_PUDDLE +J:深い毒の沼 +E:deep poisonous puddle +G:~:g +W:2 +F:LOS | PROJECT | MOVE | PLACE | REMEMBER | GLOW | POISON_PUDDLE | DEEP | CAN_FLY | +F:TELEPORTABLE + +N:234:SHALLOW_ACID_PUDDLE +J:浅い毒の沼 +E:shallow poisonous puddle +G:~:G +W:2 +F:LOS | PROJECT | MOVE | PLACE | DROP | REMEMBER | POISON_PUDDLE | SHALLOW | CAN_FLY | +F:TELEPORTABLE
そんなこんなで以下の通り追加できました。次回で実際にダンジョンにこれらの地形を生成する手段を追加します。
2018/12/20
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part110…バグ2件修正
何時もこんくらいのペースでチケット消化できればなー俺もなー。
- Thu Dec 20 23:00:21 2018 +0900: [Fix] #37551 武器修復時にアンドロイド経験値修正処理を追加。 / Add android's exp calculation on broken weapon reforging.
- Thu Dec 20 22:45:43 2018 +0900: [Fix] #37551 武器修復時の重量計算バグを修正。 / Fix calculation on broken weapon reforging.
- Thu Dec 20 22:04:08 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Thu Dec 20 22:01:57 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Thu Dec 20 21:56:31 2018 +0900: [Fix] #38259 リファクタリング時の青魔導師リピート処理エンバグ修正。 / Fix a bug of repeat process by mistake of refactoring .
2018/12/23
■ [魚類版深夜の真剣お絵描き60分一本勝負]ワカサギ
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part111…さらにバグ2件修正
こんなん直しました
- Sun Dec 23 19:33:24 2018 +0900: [Refactor] #37353 コメント整理。 / Refactor comments.
- Sun Dec 23 19:21:53 2018 +0900: [Refactor] #37481 test_hit_norm()の命中計算時にhit_chance()を呼び出すよう整理。 / Refactor that test_hit_norm() call hit_chance() for calculation.
- Sun Dec 23 19:00:18 2018 +0900: [Fix] #37481 hit_chance()をtest_hit_norm()に合わせるよう修正。 / Fix hit_chance() to fit test_hit_norm().
- Sun Dec 23 18:25:52 2018 +0900: [Refactor] #37481 test_hit_norm()の引数整理。 / Refactor arguments of test_hit_norm().
- Sun Dec 23 17:54:13 2018 +0900: [Refactor] #37481 melee.hを定義。 \ Add melee.h.
- Sun Dec 23 16:53:47 2018 +0900: [Refactor] #37481 hit_chance()をmelee1.cに移動。 \ Move hit_change() to melee1.c.
- Sun Dec 23 16:39:36 2018 +0900: [Fix] #37856 process_monster()で、時間経過自爆したモンスターの処理を中断するよう修正。 / Fix that time bomb monster's process on process_monster().
- Sun Dec 23 09:26:55 2018 +0900: [Fix] #37856 不正なモンスターのステータスを参照した際に発生し得るゼロ除算を回避。 / Avoid div 0 error on viewing status of a illegal monster.
- Sun Dec 23 08:50:31 2018 +0900: [Fix] #37353 警告修正。 / Refactor warnings.
- Sun Dec 23 08:44:31 2018 +0900: [Fix] #37856 mon_take_hit_mon()の前コミットに関する修正。 / Fix mon_take_hit_mon() about previous commit.
- Sun Dec 23 08:31:10 2018 +0900: [Feature] #37856 mon_take_hit_mon()にdeadポインタ引数を追加。 Add a pointer argument for dead status to mon_take_hit_mon().
- Sun Dec 23 08:18:41 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Sun Dec 23 08:16:14 2018 +0900: [Refactor] #37353 コメント整理 / Refactor comments.
- Sun Dec 23 07:59:58 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Sun Dec 23 07:25:33 2018 +0900: [Feature] #37856 ウィザードモードの"Q"コマンドで任意のクエストを発生中にする処理追加(バグがまだある可能性大) / Implement that wizard command 'Q' can takes any quest (Buggy)
2018/12/24
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part112…特別編「変愚蛮怒の地形実装例 ~毒沼やら酸の沼やら~(中編)」
前回はこちら。風邪でダウンしたりMtG Arenaにハマってしまったりしたのでこの件も全中後編で行きます。ゆ る し て。
グローバル変数上の定義も追加する
前回、f_info.txtで定義を追加しましたが、ダンジョンフロア作成処理向けには別途グローバル変数で各IDを加え込む処理が必要だったのでそれを追加しました。このコミットには、他にちょっとした修正も入っています。
diff --git a/src/externs.h b/src/externs.h index c639cc2..34e84b8 100644 --- a/src/externs.h +++ b/src/externs.h @@ -428,6 +428,14 @@ extern FEAT_IDX feat_deep_water; extern FEAT_IDX feat_shallow_water; extern FEAT_IDX feat_deep_lava; extern FEAT_IDX feat_shallow_lava; +extern FEAT_IDX feat_heavy_cold_zone; +extern FEAT_IDX feat_cold_zone; +extern FEAT_IDX feat_heavy_electrical_zone; +extern FEAT_IDX feat_electrical_zone; +extern FEAT_IDX feat_deep_acid_puddle; +extern FEAT_IDX feat_shallow_acid_puddle; +extern FEAT_IDX feat_deep_poisonous_puddle; +extern FEAT_IDX feat_shallow_poisonous_puddle; extern FEAT_IDX feat_dirt; extern FEAT_IDX feat_grass; extern FEAT_IDX feat_flower; diff --git a/src/init2.c b/src/init2.c index c95785d..f64375e 100644 --- a/src/init2.c +++ b/src/init2.c @@ -1737,6 +1737,14 @@ static errr init_feat_variables(void) feat_shallow_water = f_tag_to_index_in_init("SHALLOW_WATER"); feat_deep_lava = f_tag_to_index_in_init("DEEP_LAVA"); feat_shallow_lava = f_tag_to_index_in_init("SHALLOW_LAVA"); + feat_heavy_cold_zone = f_tag_to_index_in_init("HEAVY_COLD_ZONE"); + feat_cold_zone = f_tag_to_index_in_init("COLD_ZONE"); + feat_heavy_electrical_zone = f_tag_to_index_in_init("HEAVY_ELECTRICAL_ZONE"); + feat_electrical_zone = f_tag_to_index_in_init("ELECTRICAL_ZONE"); + feat_deep_acid_puddle = f_tag_to_index_in_init("DEEP_ACID_PUDDLE"); + feat_shallow_acid_puddle = f_tag_to_index_in_init("SHALLOW_ACID_PUDDLE"); + feat_deep_poisonous_puddle = f_tag_to_index_in_init("DEEP_POISONOUS_PUDDLE"); + feat_shallow_poisonous_puddle = f_tag_to_index_in_init("SHALLOW_POISONOUS_PUDDLE"); feat_dirt = f_tag_to_index_in_init("DIRT"); feat_grass = f_tag_to_index_in_init("GRASS"); feat_flower = f_tag_to_index_in_init("FLOWER"); diff --git a/src/variable.c b/src/variable.c index fd8958e..f8cf1b9 100644 --- a/src/variable.c +++ b/src/variable.c @@ -935,6 +935,14 @@ FEAT_IDX feat_deep_water; FEAT_IDX feat_shallow_water; FEAT_IDX feat_deep_lava; FEAT_IDX feat_shallow_lava; +FEAT_IDX feat_heavy_cold_zone; +FEAT_IDX feat_cold_zone; +FEAT_IDX feat_heavy_electrical_zone; +FEAT_IDX feat_electrical_zone; +FEAT_IDX feat_deep_acid_puddle; +FEAT_IDX feat_shallow_acid_puddle; +FEAT_IDX feat_deep_poisonous_puddle; +FEAT_IDX feat_shallow_poisonous_puddle; FEAT_IDX feat_dirt; FEAT_IDX feat_grass; FEAT_IDX feat_flower; --
d_info.txt向けのダンジョンフラグを追加する
- Mon Dec 24 22:37:02 2018 +0900: [Feature] #38635 d_info.txt向けの新フラグ4種追加 / Add 4 flags for d_info.txt.
これらの地形をさらにダンジョンフロアに生成するためのフラグを作成し、それを各ダンジョンの定義を行う、d_info.txtに追加します。
diff --git a/src/init1.c b/src/init1.c index 8b4d290..4f3f150 100644 --- a/src/init1.c +++ b/src/init1.c @@ -963,8 +963,8 @@ static cptr d_info_flags1[] = "CAVE", "CAVERN", "ARCADE", - "XXX", - "XXX", + "LAKE_ACID", + "LAKE_POISONOUS", "XXX", "FORGET", "LAKE_WATER", @@ -980,8 +980,8 @@ static cptr d_info_flags1[] = "NO_MELEE", "CHAMELEON", "DARKNESS", - "XXX", - "XXX" + "ACID_RIVER", + "POISONOUS_RIVER" };
新たに適用されるダンジョンは、まあそれっぽいものに。
--- lib/edit/d_info.txt | 6 ++++++ src/init1.c | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/edit/d_info.txt b/lib/edit/d_info.txt index cdb6f3f..5aa9142 100644 --- a/lib/edit/d_info.txt +++ b/lib/edit/d_info.txt @@ -62,6 +62,7 @@ L:FLOOR:100:FLOOR:0:FLOOR:0:50 A:GRANITE:100:GRANITE:0:GRANITE:0:GRANITE:GRANITE:MAGMA_VEIN:QUARTZ_VEIN F:CAVERN | WATER_RIVER | LAVA_RIVER | ARENA | DESTROY | CURTAIN | GLASS_ROOM | F:LAKE_WATER | LAKE_LAVA | LAKE_RUBBLE | LAKE_TREE | ARCADE +F:LAKE_ACID | ACID_RIVER | LAKE_POISONOUS | POISONOUS_RIVER F:MONSTER_DIV_64 N:2:イークの洞穴 @@ -111,6 +112,7 @@ A:GRANITE:90:DARK_PIT:10:GRANITE:0:GRANITE:GRANITE:MAGMA_VEIN:DARK_PIT F:BIG | LAVA_RIVER | CAVERN | DESTROY F:MONSTER_DIV_10 F:CAVE | LAKE_LAVA | LAKE_TREE | LAKE_RUBBLE +F:LAKE_ACID | ACID_RIVER | LAKE_POISONOUS | POISONOUS_RIVER M:DRAGON | R_CHAR_dD # Vecna is there, guarding Soulsword @@ -124,6 +126,7 @@ L:FLOOR:85:SHALLOW_WATER:15:FLOOR:0:30 A:GRANITE:75:DARK_PIT:25:GRANITE:0:GRANITE:GRANITE:SHALLOW_WATER:DEEP_WATER F:MONSTER_DIV_4 | FINAL_GUARDIAN_804 | FINAL_ARTIFACT_89 F:WATER_RIVER | DESTROY | ARENA | LAKE_WATER | LAKE_RUBBLE | DESTROY +F:LAKE_POISONOUS | POISONOUS_RIVER M:UNDEAD | NONLIVING N:7:森 @@ -208,6 +211,7 @@ L:FLOOR:50:SHALLOW_WATER:30:DEEP_WATER:20:100 A:GRANITE:100:GRANITE:0:GRANITE:0:GRANITE:GRANITE:SHALLOW_WATER:DEEP_WATER F:MONSTER_DIV_16 | ARENA | WATER_RIVER | LAKE_WATER | F:FINAL_GUARDIAN_857 | FINAL_ARTIFACT_129 +F:LAKE_ACID | ACID_RIVER | LAKE_POISONOUS | POISONOUS_RIVER M:DEMON | ELDRITCH_HORROR N:14:山 @@ -232,6 +236,7 @@ L:FLOOR:100:FLOOR:0:FLOOR:0:0 A:GRANITE:60:MAGMA_TREASURE:20:QUARTZ_TREASURE:20:GRANITE:GRANITE:MAGMA_VEIN:QUARTZ_VEIN F:MONSTER_DIV_1 | WATER_RIVER | CAVE | CAVERN | SMALLEST F:LAVA_RIVER | DESTROY +F:LAKE_ACID | ACID_RIVER M:R_CHAR_$ N:16:反魔法の洞窟 @@ -281,6 +286,7 @@ L:FLOOR:100:FLOOR:0:FLOOR:0:50 A:GRANITE:100:GRANITE:0:GRANITE:0:GRANITE:GRANITE:MAGMA_VEIN:QUARTZ_VEIN F:CAVERN | WATER_RIVER | LAVA_RIVER | ARENA | DESTROY | GLASS_ROOM | F:LAKE_WATER | LAKE_LAVA | LAKE_RUBBLE | LAKE_TREE +F:LAKE_ACID | ACID_RIVER | LAKE_POISONOUS | POISONOUS_RIVER F:MONSTER_DIV_64 | DARKNESS | FINAL_GUARDIAN_803 N:20:ガラスの城
ACID_RIVERとPOISONOUS_RIVERを実装する。
溶岩の川の実装をベースに。普通の川を先に優先しつつ、そちらが選ばれなければフラグのある限り、他の川を当確率に指定します。
diff --git a/src/floor-generate.c b/src/floor-generate.c index 77b11d3..fb33ba0 100644 --- a/src/floor-generate.c +++ b/src/floor-generate.c @@ -711,20 +711,43 @@ static bool cave_gen(void) /* Hack -- Add some rivers */ if (one_in_(3) && (randint1(dun_level) > 5)) { - IDX feat1 = 0, feat2 = 0; + FEAT_IDX feat1 = 0, feat2 = 0; - /* Choose water or lava */ + /* Choose water mainly */ if ((randint1(MAX_DEPTH * 2) - 1 > dun_level) && (d_info[dungeon_type].flags1 & DF1_WATER_RIVER)) { feat1 = feat_deep_water; feat2 = feat_shallow_water; } - else if (d_info[dungeon_type].flags1 & DF1_LAVA_RIVER) + else /* others */ { - feat1 = feat_deep_lava; - feat2 = feat_shallow_lava; + FEAT_IDX select_deep_feat[10]; + FEAT_IDX select_shallow_feat[10]; + int select_id_max = 0, selected; + + if (d_info[dungeon_type].flags1 & DF1_LAVA_RIVER) + { + select_deep_feat[select_id_max] = feat_deep_lava; + select_shallow_feat[select_id_max] = feat_shallow_lava; + select_id_max++; + } + if (d_info[dungeon_type].flags1 & DF1_POISONOUS_RIVER) + { + select_deep_feat[select_id_max] = feat_deep_poisonous_puddle; + select_shallow_feat[select_id_max] = feat_shallow_poisonous_puddle; + select_id_max++; + } + if (d_info[dungeon_type].flags1 & DF1_ACID_RIVER) + { + select_deep_feat[select_id_max] = feat_deep_acid_puddle; + select_shallow_feat[select_id_max] = feat_shallow_acid_puddle; + select_id_max++; + } + + selected = randint1(select_id_max); + feat1 = select_deep_feat[selected]; + feat2 = select_shallow_feat[selected]; } - else feat1 = 0; if (feat1) { --
んでもって
で き ま し た。
冷気と電撃、他に池などは引き続き次回の明日に。
2018/12/25
■ [変愚蛮怒/攻略] 変愚蛮怒開発日誌part113…特別編「変愚蛮怒の地形実装例 ~毒沼やら酸の沼やら~(後編)」
相変わらずトリを欲しがる割には盛り上がらない最後ですが、前回の続きで最後です。
前提:新しい固定部屋生成処理を追加してみる
前回までで溶岩と同じ要領で、酸と毒の川を作成しました。このまま同じように冷気と電撃もなし崩しにやっていいのかもしれませんが、基本的に川として生成される要素ではない気もします。
そこで今回は、これまで大きく分けて16種類だった部屋生成に17番目の「特殊固定部屋」を設定し(実はこの件より前に実装したものだったりしますが)v_info.txtにこれまで実装された地形を追加してみましょう。 これまでの部屋については、
- Type1(基本長方形部屋)
- Type2(長方形二つ重ね部屋)
- Type3(十字部屋)
- Type4(二重部屋)
- Type5(モンスターネスト)
- Type6(モンスターピット)
- Type7/8(小型/大型Vault)
- Type9(フラクタル生成部屋)
- Type10(ランダムVault)
- Type11(円形部屋)
- Type12(聖堂)
- Type13(トラップつきモンスター・ピット)
- Type14(トラップ部屋)
- Type15(ガラス部屋)
- Type16(地下街)
なども参照ください。
今回作成するType17は、このうち、Type7/8の固定Vaultと同じように、v_info.txtで予め作られた固定の地形を生成する形にします。固定Vaultとの違いは、単純にアイテムや大量の深層的が生成されず、比較的部屋の生成確率を高くする、それだけです。
Type17(特殊固定部屋)の処理実装実装
基本、Type7/8のコピペです。いやDRY精神に則ると随分とアレですが。いずれ直します(すぐ直すとは言ってない)
@@ -109,6 +110,7 @@ static byte room_build_order[ROOM_T_MAX] = { ROOM_T_OVERLAP, ROOM_T_CROSS, ROOM_T_FRACAVE, + ROOM_T_FIXED, ROOM_T_NORMAL, }; @@ -2072,6 +2074,7 @@ static bool room_build(int typ) case ROOM_T_TRAP: return build_type14(); case ROOM_T_GLASS: return build_type15(); case ROOM_T_ARCADE: return build_type16(); + case ROOM_T_FIXED: return build_type17(); } /* Paranoia */ diff --git a/src/rooms.h b/src/rooms.h index 51f8209..97d3b43 100644 --- a/src/rooms.h +++ b/src/rooms.h @@ -39,8 +39,9 @@ #define ROOM_T_TRAP 13 /* Piranha/Armageddon trap room */ #define ROOM_T_GLASS 14 /* Glass room */ #define ROOM_T_ARCADE 15 /* Arcade */ +#define ROOM_T_FIXED 16 /* Fixed room */ -#define ROOM_T_MAX 16 +#define ROOM_T_MAX 17
素直に#define定義を追加し、
--- a/src/rooms.c +++ b/src/rooms.c @@ -89,6 +89,7 @@ static room_info_type room_info_normal[ROOM_T_MAX] = {{ 0, 0, 1, 1, 1, 2, 3, 4, 5, 6, 8}, 20}, /*TRAP */ {{ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2}, 40}, /*GLASS */ {{ 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3}, 1}, /*ARCADE */ + {{ 20, 40, 60, 80,100,100,100,100,100,100,100}, 1}, /*FIX */ };
room_info_normalに生成確率テーブルも追加します。
v_info.txtにまず適当に足してみる
- Sat Oct 6 17:50:31 2018 +0900: [Feature] #38635 v_infoの2種部屋追加。 Add 2 rooms to v_info.
- Thu Oct 4 20:52:55 2018 +0900: [Feature] #38635 v_infoを参照する通常固定部屋の生成処理を実装。7種部屋追加。 Implement fixed room from v_info.txt, add 7 rooms.
いくつか雑に追加したうちの一部を抜粋します。
N:129:Fixed room1 X:16:8:7:7 D:%%%%%%% D:%.....% D:%.'''.% D:%.'.'.% D:%.'''.% D:%.....% D:%%%%%%% N:130:Fixed room2 X:16:8:14:14 D:%%%%%%%%%%%%%% D:%............% D:%...........%% D:%..........%% D:%.........%% D:%........%% D:%.......%% D:%......%% D:%.....%% D:%....%% D:%...%% D:%..%% D:%.%% D:%%% N:131:Fixed room3 X:16:8:7:7 D:%%%%%%% D:%..#..% D:%.'#'.% D:%##.##% D:%.'#'.% D:%..#..% D:%%%%%%% N:132:Fixed room4 X:16:8:10:10 D: %%%% D: %%##%% D: %%.. .%% D:%%.#. #.%% D:%#..##..#% D:%#..##..#% D:%%.#. #.%% D: %%.. .%% D: %%##%% D: %%%%
この時点では以下のような地形を指定できます。Xは順に部屋の型ID、レアリティ(多分働いていない)、縦の長さ、横の長さです。……17番目の部屋種別なのに16にしてしまったのはミスです、早めに直します。
地形定義はType7/8の記事でも書いてありますがv_info.txtで以下の通りです。
# % - outside of the vault, where corridors may be connected # # - granite # $ - glass wall # X - impenetrable rock # Y - impenetrable glass wall # * - treasure or trap # + - secret door # - - secret glass door # ' - curtain # ^ - trap # & - monster up to 5 levels out of depth (OOD) # @ - monster up to 11 levels OOD # 9 - monster up to 9 levels OOD and treasure up to 7 levels OOD # 8 - monster up to 40 levels OOD and treasure up to 20 levels OOD # , - monster up to 3 levels OOD and/or treasure up to 7 levels OOD
v_info.txt用の新規定義追加と該当地形を持った固定部屋を作成。
- Sat Oct 6 15:48:37 2018 +0900: [Feature] #38635 v_infoの地形定義追加。 Add feature definition for v_info.
- Tue Dec 25 21:18:44 2018 +0900: [Feature] #38635 Vault用地形定義を追加。 / Implement new vault features.
雑にバグ修正も挟まっている辺りの更新です、ご了承ください。 build_vault()関数のswitchにこんな感じに追加します。
@@ -470,6 +470,38 @@ static void build_vault(POSITION yval, POSITION xval, POSITION ymax, POSITION xm set_cave_feat(y, x, feat_deep_lava); break; + case 'f': + set_cave_feat(y, x, feat_shallow_acid_puddle); + break; + + case 'F': + set_cave_feat(y, x, feat_deep_acid_puddle); + break; + + case 'g': + set_cave_feat(y, x, feat_shallow_poisonous_puddle); + break; + + case 'G': + set_cave_feat(y, x, feat_deep_poisonous_puddle); + break; + + case 'h': + set_cave_feat(y, x, feat_cold_zone); + break; + + case 'H': + set_cave_feat(y, x, feat_heavy_cold_zone); + break; + + case 'i': + set_cave_feat(y, x, feat_electrical_zone); + break; + + case 'I': + set_cave_feat(y, x, feat_heavy_electrical_zone); + break; +
これに合わせてv_info.txtも追加します。
N:136:Spring 1 X:16:8:10:12 D: %%%%%%%% D: %%......%% D:%%..^^^^..%% D:%..^^==^^..% D:%..^====^..% D:%..^====^..% D:%..^^==^^..% D:%%..^^^^..%% D: %%......%% D: %%%%%%%% N:137:LavaSpring 1 X:16:8:10:12 D: %%%%%%%% D: %%......%% D:%%..vvvv..%% D:%..vvwwvv..% D:%..vwwwwv..% D:%..vwwwwv..% D:%..vvwwvv..% D:%%..vvvv..%% D: %%......%% D: %%%%%%%% N:138:AcidSpring 1 X:16:8:10:12 D: %%%%%%%% D: %%......%% D:%%..ffff..%% D:%..ffFFff..% D:%..fFFFFf..% D:%..fFFFFf..% D:%..ffFFff..% D:%%..ffff..%% D: %%......%% D: %%%%%%%% N:139:PoisonousSpring 1 X:16:8:10:12 D: %%%%%%%% D: %%......%% D:%%..gggg..%% D:%..ggGGgg..% D:%..gGGGGg..% D:%..gGGGGg..% D:%..ggGGgg..% D:%%..gggg..%% D: %%......%% D: %%%%%%%% N:140:ColdZone 1 X:16:8:10:12 D: %%%%%%%% D: %%......%% D:%%..hhhh..%% D:%..hhHHhh..% D:%..hHHHHh..% D:%..hHHHHh..% D:%..hhHHhh..% D:%%..hhhh..%% D: %%......%% D: %%%%%%%% N:141:ElectricalZone 1 X:16:8:10:12 D: %%%%%%%% D: %%......%% D:%%..iiii..%% D:%..iiIIii..% D:%..iIIIIi..% D:%..iIIIIi..% D:%..iiIIii..% D:%%..iiii..%% D: %%......%% D: %%%%%%%%
結果
うん、まだしょぼいですね。作るのならもっと、数も質も増やすべきです。折角v_info.txtで共通して使えるようになったのですから、Vaultでも各地形に囲われた要塞作っていいでしょう。
ついでにモンスターが該当耐性を持っているのみ地形に侵入できるよう修正
補足的なものです。こうして追加してきた地形をプレイヤーだけでなくモンスターも影響するように修正します。火耐性を持っていない敵が溶岩に侵入できないのと同様に、各属性への耐性がないと各地形に侵入できないようmonster_can_cross_terrain()を修正しておきます。
--- src/monster1.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/monster1.c b/src/monster1.c index bee3385..2e35540 100644 --- a/src/monster1.c +++ b/src/monster1.c @@ -2326,6 +2326,30 @@ bool monster_can_cross_terrain(FEAT_IDX feat, monster_race *r_ptr, BIT_FLAGS16 m if (!(r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK)) return FALSE; } + /* Cold */ + if (have_flag(f_ptr->flags, FF_COLD_PUDDLE)) + { + if (!(r_ptr->flagsr & RFR_EFF_IM_COLD_MASK)) return FALSE; + } + + /* Elec */ + if (have_flag(f_ptr->flags, FF_ELEC_PUDDLE)) + { + if (!(r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK)) return FALSE; + } + + /* Acid */ + if (have_flag(f_ptr->flags, FF_ACID_PUDDLE)) + { + if (!(r_ptr->flagsr & RFR_EFF_IM_ACID_MASK)) return FALSE; + } + + /* Poison */ + if (have_flag(f_ptr->flags, FF_POISON_PUDDLE)) + { + if (!(r_ptr->flagsr & RFR_EFF_IM_POIS_MASK)) return FALSE; + } + return TRUE; } --
最後に
今後とも精進して色々やっていきますのでどうぞよろしくお願いいたします。皆様良いお年を。
2018/12/26
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part114…定期v_info.txt追加に用語修正
雑かつ半端だが。とりあえず折角の固定部屋は追々増やしていこうかと。
- Wed Dec 26 23:39:47 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Wed Dec 26 23:29:35 2018 +0900: [Fix] #38509 「ドラゴン皮の靴」をドラゴン・ブーツに修正。 / Fix Japanese translation of 'dragon boots'.
- Wed Dec 26 23:26:48 2018 +0900: [Fix] #38509 「バシリスク」→「バジリスク」に統一。 / Unify Japanese translation of 'basilisk'.
- Wed Dec 26 23:17:09 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Wed Dec 26 13:21:47 2018 +0900: [Feature] #38635 v_info2件追加。 / Add 2 fixed rooms.
2018/12/27
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part115…定期v_info.txt追加にコメント整理
- Thu Dec 27 22:25:43 2018 +0900: [Feature] #38635 v_info2件追加。 / Add 2 fixed rooms.
- Thu Dec 27 08:19:50 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Thu Dec 27 08:12:21 2018 +0900: [Refactor] #37353 コメント整理。 / Refactor comments.
- Thu Dec 27 08:07:48 2018 +0900: [Refactor] #37353 コメント整理。 / Refactor comments.
- Thu Dec 27 08:02:47 2018 +0900: [Refactor] #37353 コメント整理。 / Refactor comments.
ご覧ください。これが深き者としては不完全な寿命を時を止める冒涜的手段で補い、人々に絶望の日曜をもたらし続ける忌まわしき一族の住処です(発狂)
なお、この泥棒やオーク達はこの後スタッフに頂かれました。
あとついでくらいに高圧電線デスマッチみたいな地形も。
2018/12/28
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part116…バグ一件修正
原因はget_mon_num() 中nasty生成を起こした際、逆に階層が浅くなりマイナス値を取ってアンダーフローを起こした結果モンスター種族IDが0を返すうえ、player_outfit() がpval=0の死体を生成するためでした。 この2件を抑止して修正完了。
ウィザードモードでアイテムを一度全部捨て、初期所持品を追加し直す処理を実装して、バグの再現を繰り返したらこうなりました。
さっきまで命だったものが辺り一面に転がる(AMZNZ)
- Fri Dec 28 16:00:06 2018 +0900: [Fix] #38813 get_mon_num() の階層アンダーフロー回避と player_outfit() が pval=0 の死体を生成しない仕様にした。 / Avoid depth underflow in get_mon_num(). player_outfit doesn't generate pval 0 corpses.
- Fri Dec 28 15:34:01 2018 +0900: [Refactor] #37353 monster_hook_human() を monsterrace-hook.c に移動。 / Move monster_hook_human() to monsterrace-hook.c.
- Fri Dec 28 15:30:02 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Fri Dec 28 15:29:29 2018 +0900: [Feature] #38813 デバッグのために暫定ウィザードコマンド実装。 / Implement temporary wizard command for debug.
- Fri Dec 28 09:03:11 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Fri Dec 28 08:51:19 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Fri Dec 28 08:31:29 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Fri Dec 28 08:26:11 2018 +0900: [Refactor] #37353 コメント整理。 / Refactor comments.
2018/12/29
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part117…定期v_info追加にリファクタリング案件進行中
この辺前々から整理すとこと思いつつ。
面倒ではあるけどうま味もそれなりにある地形も追加していっとる次第です。
- Sat Dec 29 19:20:24 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Sat Dec 29 19:12:14 2018 +0900: [Refactor] #38824 choose_object()拡張。 / expand choose_object().
- Sat Dec 29 18:44:41 2018 +0900: [Refactor] #37353 コメント整理。 / Refactor comments.
- Sat Dec 29 14:12:31 2018 +0900: [Refactor] #37353 型の置換。 / Type replacement.
- Sat Dec 29 14:05:47 2018 +0900: [Feature] #38635 固定部屋の番号付け修正(16->17) / Fix ID of fixed room (16 to 17)
- Sat Dec 29 13:57:51 2018 +0900: [Feature] #38635 v_info2件追加(+デバッグ設定差し戻し)/ Add 2 fixed rooms. (and remand debug room table...)
2018/12/30
■ [変愚蛮怒/開発] 変愚蛮怒開発日誌part118…定期v_info追加にリファクタリング案件進行中
定期。ついでにグローバル変数一つSATSUGAIしときました。
- Sun Dec 30 17:00:07 2018 +0900: [Feature] #38635 v_info3件追加。 / Add 3 fixed rooms.
- Sun Dec 30 15:45:48 2018 +0900: [Refactor] #37353 メッセージ整理。 / Refactor messages.
- Sun Dec 30 15:30:23 2018 +0900: [Refactor] #37353 コメント整理。 / Refactor comments.
- Sun Dec 30 15:27:15 2018 +0900: [Refactor] #38824 グローバル変数 select_the_force を処理。 / Refactor select_the_force, a global variable.
- Sun Dec 30 14:30:58 2018 +0900: [Refactor] #38824 cmd5.c の get_item() を choose_object() に置換。 / Replace from get_item() to choose_object() in cmd5..
- Sun Dec 30 13:48:45 2018 +0900: [Refactor] #38824 bldg.c と cmd2.c の get_item() を choose_object() に置換中。 / Replace from get_item() to choose_object() in bldg.c and cmd2.c.
- Sun Dec 30 13:30:53 2018 +0900: [Refactor] #38824 choose_object()の修正とget_item()の置換。 / Fix choose_object() and replace from get_item().
2018/12/31
■ [変愚蛮怒/開発]変愚蛮怒開発日誌part119…定期v_infoにモンスター大量追加、リリースノート整理再開
年末最後の最後になって、創作面で世話になっていた人の訃報とか来てショックですが、正直、なればこそ自分も少しは急いでやることやってかんと思ったり。
今回ぐりっどばぐでHourierさんからいただいたコボルト系モンスターを同チャンネルで相談しつつ追加してみました。2.2.2正式リリースまでに調整します。
- Mon Dec 31 09:11:05 2018 +0900: [Feature] #37285 Hourier氏のコボルド系モンスター11種追加。 / Add 11 kobold monsters by Hourier.
- Mon Dec 31 08:42:28 2018 +0900: [Refactor] #37353 ソース整理。 / Refactor sources.
- Mon Dec 31 08:36:02 2018 +0900: [Refactor] #37353 project_hack() を project_all_los()に改名。 / Refactor project_hack() to project_all_los().
- Mon Dec 31 08:27:12 2018 +0900: [Refactor] #37353 コメント整理。 / Refactor comments.
- Mon Dec 31 08:04:50 2018 +0900: [Fix] #38827 調査時、速度表示のアンダーフローを一時的に修正。 / Fix underflow calculation for probing temporarily.
- Mon Dec 31 07:47:20 2018 +0900: [Feature] #38635 v_info2件追加。 / Add 2 fixed rooms.
それといい加減Web、特にリリースノートの整理はせにゃならんと思っていますので、進めます。ひとまず皆さま良いお年を。
■ sunawa [ぼくも仕事中にArenaのデッキレシピ考えてるせいで仕事が進みません(半ギレ) 酸の沼はくさそう、冷気属性の床はス..]
■ deskull [毒とかもう岡山の県北が-more- Arenaいいですよね、もう当分中毒です(マジキチスマイル)]