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などでご質問もどうぞ(震え声)