bcdice 3.13.0 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +104 -0
- data/i18n/Arianrhod/ko_kr.yml +3 -0
- data/i18n/Cthulhu/en_us.yml +11 -0
- data/i18n/Cthulhu/zh_hant.yml +1 -1
- data/i18n/CyberpunkRed/ja_jp.yml +389 -0
- data/i18n/CyberpunkRed/ko_kr.yml +389 -0
- data/i18n/DoubleCross/ja_jp.yml +53 -0
- data/i18n/DoubleCross/ko_kr.yml +52 -0
- data/i18n/FinalFantasyXIV/en_us.yml +4 -0
- data/i18n/FinalFantasyXIV/ja_jp.yml +4 -0
- data/i18n/FutariSousa/ja_jp.yml +284 -127
- data/i18n/KillDeathBusiness/ja_jp.yml +198 -0
- data/i18n/KizunaBullet/ja_jp.yml +653 -0
- data/i18n/MagicaLogia/ko_kr.yml +2 -2
- data/i18n/MonotoneMuseum/ja_jp.yml +246 -14
- data/i18n/MonotoneMuseum/ko_kr.yml +227 -0
- data/i18n/SkynautsBouken/ja_jp.yml +114 -0
- data/i18n/SkynautsBouken/ko_kr.yml +114 -0
- data/i18n/StratoShout/ko_kr.yml +102 -102
- data/i18n/TensaiGunshiNiNaro/ja_jp.yml +126 -0
- data/i18n/UnsungDuet/ja_jp.yml +62 -0
- data/i18n/UnsungDuet/ko_kr.yml +62 -0
- data/i18n/en_us.yml +5 -0
- data/i18n/zh_hant.yml +5 -0
- data/lib/bcdice/dice_table/range_table.rb +24 -0
- data/lib/bcdice/game_system/Agnostos.rb +248 -0
- data/lib/bcdice/game_system/Aionia.rb +131 -0
- data/lib/bcdice/game_system/AniMalus.rb +99 -59
- data/lib/bcdice/game_system/Arianrhod_Korean.rb +32 -0
- data/lib/bcdice/game_system/ArknightsFan.rb +245 -87
- data/lib/bcdice/game_system/BlackJacket.rb +244 -0
- data/lib/bcdice/game_system/BlackJacket_Korean.rb +244 -0
- data/lib/bcdice/game_system/CharonSanctions.rb +112 -0
- data/lib/bcdice/game_system/ConvictorDrive.rb +5 -4
- data/lib/bcdice/game_system/Cthulhu7th.rb +1 -1
- data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional/full_auto.rb +293 -0
- data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional/rollable.rb +43 -0
- data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional.rb +470 -306
- data/lib/bcdice/game_system/Cthulhu_English.rb +59 -0
- data/lib/bcdice/game_system/CyberpunkRed.rb +15 -6
- data/lib/bcdice/game_system/CyberpunkRed_Korean.rb +66 -0
- data/lib/bcdice/game_system/DivineCharger.rb +841 -0
- data/lib/bcdice/game_system/DoubleCross.rb +18 -1
- data/lib/bcdice/game_system/DoubleCross_Korean.rb +5 -1
- data/lib/bcdice/game_system/FinalFantasyXIV.rb +115 -0
- data/lib/bcdice/game_system/FinalFantasyXIV_English.rb +39 -0
- data/lib/bcdice/game_system/FullFace.rb +63 -12
- data/lib/bcdice/game_system/FutariSousa.rb +105 -13
- data/lib/bcdice/game_system/Garactier.rb +479 -0
- data/lib/bcdice/game_system/GardenOrder.rb +390 -9
- data/lib/bcdice/game_system/GundogRevised.rb +8 -8
- data/lib/bcdice/game_system/Insane_Korean.rb +1 -1
- data/lib/bcdice/game_system/InvisibleLiar.rb +79 -0
- data/lib/bcdice/game_system/KillDeathBusiness.rb +155 -3
- data/lib/bcdice/game_system/KimitoYell.rb +568 -0
- data/lib/bcdice/game_system/KizunaBullet.rb +240 -0
- data/lib/bcdice/game_system/KyokoShinshoku.rb +51 -8
- data/lib/bcdice/game_system/Magius.rb +125 -0
- data/lib/bcdice/game_system/Magius_3rdNewTokyoCity.rb +62 -0
- data/lib/bcdice/game_system/MonotoneMuseum.rb +14 -1
- data/lib/bcdice/game_system/MonotoneMuseum_Korean.rb +4 -4
- data/lib/bcdice/game_system/NRR.rb +2 -2
- data/lib/bcdice/game_system/NSSQ.rb +17 -9
- data/lib/bcdice/game_system/NervWhitePaper.rb +129 -0
- data/lib/bcdice/game_system/RogueLikeHalf.rb +198 -0
- data/lib/bcdice/game_system/RuneQuestRoleplayingInGlorantha.rb +16 -13
- data/lib/bcdice/game_system/ShinobiGami.rb +73 -43
- data/lib/bcdice/game_system/ShuumatsuBargainWars.rb +203 -0
- data/lib/bcdice/game_system/SkynautsBouken.rb +49 -134
- data/lib/bcdice/game_system/SkynautsBouken_Korean.rb +57 -0
- data/lib/bcdice/game_system/StratoShout_Korean.rb +1 -1
- data/lib/bcdice/game_system/SwordWorld.rb +5 -1
- data/lib/bcdice/game_system/SwordWorld2_5.rb +3 -2
- data/lib/bcdice/game_system/TensaiGunshiNiNaro.rb +262 -0
- data/lib/bcdice/game_system/TheIndieHack.rb +82 -0
- data/lib/bcdice/game_system/TheOneRing2nd.rb +406 -0
- data/lib/bcdice/game_system/TheUnofficialHollowKnightRPG.rb +185 -0
- data/lib/bcdice/game_system/TorgEternity.rb +35 -6
- data/lib/bcdice/game_system/TrailOfCthulhu.rb +139 -0
- data/lib/bcdice/game_system/UnsungDuet.rb +17 -75
- data/lib/bcdice/game_system/UnsungDuet_Korean.rb +41 -0
- data/lib/bcdice/game_system/Utakaze.rb +55 -2
- data/lib/bcdice/game_system/Warhammer4.rb +124 -3
- data/lib/bcdice/game_system/WoW.rb +161 -0
- data/lib/bcdice/game_system/YankeeMustDie.rb +192 -0
- data/lib/bcdice/game_system/YearZeroEngine.rb +225 -28
- data/lib/bcdice/game_system/Yotabana.rb +62 -0
- data/lib/bcdice/game_system/YuMyoKishi.rb +141 -0
- data/lib/bcdice/game_system/cyberpunk_red/tables.rb +111 -473
- data/lib/bcdice/game_system/kizuna_bullet/tables.rb +171 -0
- data/lib/bcdice/game_system/sword_world/rating_lexer.rb +1 -0
- data/lib/bcdice/game_system/sword_world/rating_options.rb +4 -1
- data/lib/bcdice/game_system/sword_world/rating_parsed.rb +5 -0
- data/lib/bcdice/game_system/sword_world/rating_parser.rb +129 -115
- data/lib/bcdice/game_system.rb +31 -0
- data/lib/bcdice/version.rb +1 -1
- metadata +50 -6
@@ -0,0 +1,406 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BCDice
|
4
|
+
module GameSystem
|
5
|
+
class TheOneRing2nd < Base
|
6
|
+
# ゲームシステムの識別子
|
7
|
+
ID = "TheOneRing2nd"
|
8
|
+
|
9
|
+
# ゲームシステム名
|
10
|
+
NAME = "一つの指輪:指輪物語TRPG2版"
|
11
|
+
|
12
|
+
# ゲームシステム名の読みがな
|
13
|
+
SORT_KEY = "ひとつのゆひわゆひわものかたりTRPG2"
|
14
|
+
|
15
|
+
HELP_MESSAGE = <<~TEXT
|
16
|
+
・判定コマンド(nRG[x][@y][Az][f[0|1]][i[0|1]][w[0|1]][m[0|1]])
|
17
|
+
判定用に難易度nを指定して判定ダイスを振る。技量ダイスx、痛打判定値y、修正値zを指定可能。
|
18
|
+
技量ダイス、痛打判定値、修正値は0、または未指定(0と同じ)にできる。
|
19
|
+
痛打判定値の0、未指定は痛打判定を行わない。
|
20
|
+
修正値は判定合計値に加算され、「ガンダルフ・ルーン」や「サウロンの目」はその影響を受けない。
|
21
|
+
例1: 13RG (難易度13 技量ダイス0個)
|
22
|
+
例2: 13RG3 (難易度13 技量ダイス3個)
|
23
|
+
例3: 13RG3@10A1 (難易度13 技量ダイス3個、痛打判定10、結果に1を加算)
|
24
|
+
|
25
|
+
・表用コマンド(FD[x][f[0|1]][i[0|1]])
|
26
|
+
表用に判定ダイスを振る。修正値xが指定可能。修正値は0、あるいは未指定(0と同じ)にできる。
|
27
|
+
「ガンダルフ・ルーン」や「サウロンの目」は修正値の影響を受けず、値が10を越えることもない。
|
28
|
+
例1: FD (1d12で判定)
|
29
|
+
例2: FD1 (1d12で判定し、ダイス目に+1修正)
|
30
|
+
|
31
|
+
・コマンドオプション
|
32
|
+
オプションは、判定コマンドなら4個まで、表用コマンドなら2個まで、順不同で指定可能(重複可)。
|
33
|
+
f: 有利(favoured)オプション。不利と同時指定時は相殺。選択された値に◎。
|
34
|
+
i: 不利(ill-favoured)オプション。有利と同時指定時は相殺。選択された値に◎。
|
35
|
+
例1: 13RG3f (難易度13 技量ダイス3個、有利)
|
36
|
+
例2: FD1f (1修正、有利)
|
37
|
+
例3: 13RG3if (難易度13 技量ダイス3個、不利、有利)
|
38
|
+
※有利/不利は相殺。
|
39
|
+
|
40
|
+
判定コマンドでは更に下記のオプションを同じ条件で指定可能。
|
41
|
+
w: 疲労(weary)状態オプション。
|
42
|
+
m: 絶望(miserable)状態オプション。
|
43
|
+
例1: 13RG3wf (難易度13 技量ダイス3個、疲労状態、有利)
|
44
|
+
例2: 13RG3fiwm (難易度13 技量ダイス3個、有利、不利、疲労状態、絶望状態)
|
45
|
+
※有利/不利は相殺。最大オプション数である4つを指定。
|
46
|
+
|
47
|
+
・オプションスイッチ
|
48
|
+
指定したオプションのon/offを1/0で指定可能。1はon、0はoffを表す。
|
49
|
+
複数の同じオプションへのスイッチ指定は、最後のスイッチが有効となる。
|
50
|
+
例1: 13RG3if0 (難易度13 技量ダイス3個、不利はon、有利はoff)
|
51
|
+
※ 有利指定がoffのため、相殺されず不利となる。
|
52
|
+
例2: 13RG3f1f0 (難易度13 技量ダイス3個、有利は最終的にoff)
|
53
|
+
TEXT
|
54
|
+
|
55
|
+
register_prefix('\d+RG', 'FD')
|
56
|
+
|
57
|
+
SAURONS_EYE_NUMBER = 11 # サウロンの目
|
58
|
+
GANDALF_RUNE_NUMBER = 12 # ガンダルフ・ルーン
|
59
|
+
|
60
|
+
CHOICE_DIE_MARK = '◎' # 有利/不利の状態で選択されたダイスにつけるマーク
|
61
|
+
|
62
|
+
# 有利/不利状態のenum
|
63
|
+
module FavouredState
|
64
|
+
NORMAL = -98 # 通常状態
|
65
|
+
FAVOURED = -99 # 有利状態
|
66
|
+
ILLFAVOURED = -100 # 不利状態
|
67
|
+
end
|
68
|
+
|
69
|
+
def eval_game_system_specific_command(command)
|
70
|
+
case command
|
71
|
+
when /^\d+RG/i
|
72
|
+
return rg_command_exec(command)
|
73
|
+
when /^FD/i
|
74
|
+
return fd_command_exec(command)
|
75
|
+
end
|
76
|
+
return "Error" # 到達しないはずだが、念のため
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# ================ RG/FGコマンド共有メソッド等 ================#
|
82
|
+
|
83
|
+
# オプションデータクラス
|
84
|
+
class OptionData
|
85
|
+
attr_reader :favoured_state, :weary, :miserable
|
86
|
+
|
87
|
+
def initialize(favoured_state_value: FavouredState::NORMAL, weary_condition: false, miserable_condition: false)
|
88
|
+
@favoured_state = favoured_state_value
|
89
|
+
@weary = weary_condition
|
90
|
+
@miserable = miserable_condition
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# 指定された修正値文字列を取得
|
95
|
+
def get_adjust_number_text(adjust_number)
|
96
|
+
adjust_number_text = ""
|
97
|
+
|
98
|
+
if adjust_number > 0
|
99
|
+
adjust_number_text = "+#{adjust_number}"
|
100
|
+
elsif adjust_number < 0
|
101
|
+
adjust_number_text = adjust_number.to_s
|
102
|
+
end
|
103
|
+
|
104
|
+
return adjust_number_text
|
105
|
+
end
|
106
|
+
|
107
|
+
# 指定された状態文字列を取得
|
108
|
+
def get_condition_text(opts)
|
109
|
+
if opts.favoured_state == FavouredState::NORMAL && !opts.weary && !opts.miserable
|
110
|
+
return ""
|
111
|
+
end
|
112
|
+
|
113
|
+
condition_text = "\n状態:"
|
114
|
+
if opts.favoured_state == FavouredState::FAVOURED
|
115
|
+
condition_text = "#{condition_text}有利 "
|
116
|
+
elsif opts.favoured_state == FavouredState::ILLFAVOURED
|
117
|
+
condition_text = "#{condition_text}不利 "
|
118
|
+
end
|
119
|
+
if opts.weary
|
120
|
+
condition_text = "#{condition_text}疲労 "
|
121
|
+
end
|
122
|
+
if opts.miserable
|
123
|
+
condition_text = "#{condition_text}絶望 "
|
124
|
+
end
|
125
|
+
|
126
|
+
return condition_text.rstrip
|
127
|
+
end
|
128
|
+
|
129
|
+
# 指定された状態文字列を取得
|
130
|
+
def get_options(opt_params)
|
131
|
+
favoured_state_value = FavouredState::NORMAL
|
132
|
+
miserable_condition = false
|
133
|
+
weary_condition = false
|
134
|
+
|
135
|
+
opt_params.each do |x|
|
136
|
+
case x[/[WFIM]/]
|
137
|
+
when "W"
|
138
|
+
weary_condition = on_option_switch?(x)
|
139
|
+
when "F"
|
140
|
+
favoured_state_value = get_favoured_state(on_option_switch?(x), favoured_state_value, FavouredState::FAVOURED)
|
141
|
+
when "I"
|
142
|
+
favoured_state_value = get_favoured_state(on_option_switch?(x), favoured_state_value, FavouredState::ILLFAVOURED)
|
143
|
+
when "M"
|
144
|
+
miserable_condition = on_option_switch?(x)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
return OptionData.new(favoured_state_value: favoured_state_value, weary_condition: weary_condition, miserable_condition: miserable_condition)
|
149
|
+
end
|
150
|
+
|
151
|
+
# オプションから有利/不利状態指定を取得
|
152
|
+
def get_favoured_state(option_switch, before_favoured_state_value, tagert_state_type)
|
153
|
+
if option_switch
|
154
|
+
if before_favoured_state_value == tagert_state_type || before_favoured_state_value == FavouredState::NORMAL
|
155
|
+
return tagert_state_type
|
156
|
+
end
|
157
|
+
|
158
|
+
return FavouredState::NORMAL
|
159
|
+
else
|
160
|
+
if before_favoured_state_value == tagert_state_type
|
161
|
+
return FavouredState::NORMAL
|
162
|
+
end
|
163
|
+
end
|
164
|
+
return before_favoured_state_value
|
165
|
+
end
|
166
|
+
|
167
|
+
# オプションのON/OFFを取得
|
168
|
+
def on_option_switch?(opt_value)
|
169
|
+
if opt_value.length == 1 || opt_value[1..opt_value.length].to_i > 0
|
170
|
+
return true
|
171
|
+
end
|
172
|
+
|
173
|
+
return false
|
174
|
+
end
|
175
|
+
|
176
|
+
# 技量ダイスロールを行う
|
177
|
+
def make_successdice_roll(success_dice_count, weary_condition)
|
178
|
+
dice_list = @randomizer.roll_barabara(success_dice_count, 6)
|
179
|
+
success_count = dice_list.count(6)
|
180
|
+
if weary_condition
|
181
|
+
success_total_number = dice_list.reject { |i| i <= 3 }.sum
|
182
|
+
else
|
183
|
+
success_total_number = dice_list.sum
|
184
|
+
end
|
185
|
+
return dice_list.to_s, success_total_number, success_count
|
186
|
+
end
|
187
|
+
|
188
|
+
# 判定ダイスロールを行う
|
189
|
+
def make_featdice_roll(favoured_state_value)
|
190
|
+
feat_dice_count = favoured_state_value == FavouredState::NORMAL ? 1 : 2
|
191
|
+
dice_list = @randomizer.roll_barabara(feat_dice_count, 12)
|
192
|
+
|
193
|
+
choice_die_number = die_choice(dice_list, favoured_state_value)
|
194
|
+
if feat_dice_count > 1
|
195
|
+
|
196
|
+
choice_index = dice_list.find_index(choice_die_number)
|
197
|
+
|
198
|
+
first_die = "#{CHOICE_DIE_MARK if choice_index == 0}#{get_specal_die_str(dice_list[0])}"
|
199
|
+
second_die = "#{CHOICE_DIE_MARK if choice_index == 1}#{get_specal_die_str(dice_list[1])}"
|
200
|
+
|
201
|
+
feat_result_text = "[#{first_die}, #{second_die}]"
|
202
|
+
else
|
203
|
+
feat_result_text = "[#{get_specal_die_str(choice_die_number)}]"
|
204
|
+
end
|
205
|
+
|
206
|
+
return feat_result_text, choice_die_number, feat_dice_count
|
207
|
+
end
|
208
|
+
|
209
|
+
# 有利/不利を含めて判定ダイスの結果を取得
|
210
|
+
def die_choice(dice_list, favoured_state_value)
|
211
|
+
if favoured_state_value == FavouredState::ILLFAVOURED
|
212
|
+
if dice_list.count(SAURONS_EYE_NUMBER) >= 1
|
213
|
+
return SAURONS_EYE_NUMBER
|
214
|
+
else
|
215
|
+
return dice_list.min
|
216
|
+
end
|
217
|
+
elsif favoured_state_value == FavouredState::FAVOURED
|
218
|
+
if dice_list.count(GANDALF_RUNE_NUMBER) >= 1
|
219
|
+
return GANDALF_RUNE_NUMBER
|
220
|
+
else
|
221
|
+
# ガンダルフ・ルーンが無ければサウロンの目を除いた最大値を選ぶ
|
222
|
+
# ※ どちらもサウロンの目ならサウロンの目を返す
|
223
|
+
return dice_list.count(SAURONS_EYE_NUMBER) == 2 ? SAURONS_EYE_NUMBER : dice_list.reject { |x| x == SAURONS_EYE_NUMBER }.max
|
224
|
+
end
|
225
|
+
end
|
226
|
+
return dice_list[0]
|
227
|
+
end
|
228
|
+
|
229
|
+
# 判定ダイスが特殊ダイス目だった場合、該当文字列に変換する
|
230
|
+
def get_specal_die_str(die_number)
|
231
|
+
if die_number == GANDALF_RUNE_NUMBER
|
232
|
+
return "ガンダルフ・ルーン"
|
233
|
+
elsif die_number == SAURONS_EYE_NUMBER
|
234
|
+
return "サウロンの目"
|
235
|
+
end
|
236
|
+
|
237
|
+
return die_number
|
238
|
+
end
|
239
|
+
|
240
|
+
# ================ FDコマンド ================#
|
241
|
+
|
242
|
+
FD_ADJUST_NUMBER_INDEX = 2
|
243
|
+
FD_OPTION_START_INDEX = 3
|
244
|
+
|
245
|
+
# FDコマンド実行
|
246
|
+
def fd_command_exec(command)
|
247
|
+
m = /\A(FD)(-?\d*)?([FI]-?\d*)?([FI]-?\d*)?$/.match(command)
|
248
|
+
unless m
|
249
|
+
return ''
|
250
|
+
end
|
251
|
+
|
252
|
+
# コマンドパラメータ取得
|
253
|
+
adjust_number, opts = get_fd_params(m)
|
254
|
+
|
255
|
+
# 判定ダイス処理
|
256
|
+
feat_result_text, feat_die_number, feat_dice_count = make_featdice_roll(opts.favoured_state)
|
257
|
+
result_header_text = "(#{feat_dice_count}D12"
|
258
|
+
|
259
|
+
return get_fd_roll_result(result_header_text, feat_result_text, feat_die_number, feat_dice_count, adjust_number)
|
260
|
+
end
|
261
|
+
|
262
|
+
# FDコマンド判定結果の取得
|
263
|
+
def get_fd_roll_result(result_header_text, feat_result_text, feat_die_number, feat_dice_count, adjust_number)
|
264
|
+
# 修正値処理
|
265
|
+
reslt_die_number, adjust_number_text = get_fd_adjust(feat_die_number, adjust_number)
|
266
|
+
|
267
|
+
result_header_text = "#{result_header_text}#{adjust_number_text}) > #{feat_result_text}#{adjust_number_text}"
|
268
|
+
if adjust_number != 0 || feat_dice_count != 1
|
269
|
+
return "#{result_header_text} > [#{get_specal_die_str(reslt_die_number)}]"
|
270
|
+
end
|
271
|
+
|
272
|
+
return result_header_text
|
273
|
+
end
|
274
|
+
|
275
|
+
# FDコマンドの修正値取得
|
276
|
+
def get_fd_adjust(feat_die_number, adjust_number)
|
277
|
+
if [SAURONS_EYE_NUMBER, GANDALF_RUNE_NUMBER].include?(feat_die_number)
|
278
|
+
return feat_die_number, get_adjust_number_text(adjust_number)
|
279
|
+
end
|
280
|
+
|
281
|
+
res_total_num = feat_die_number + adjust_number
|
282
|
+
if res_total_num > 10
|
283
|
+
res_total_num = 10
|
284
|
+
elsif res_total_num < 1
|
285
|
+
res_total_num = 1
|
286
|
+
end
|
287
|
+
return res_total_num, get_adjust_number_text(adjust_number)
|
288
|
+
end
|
289
|
+
|
290
|
+
# FDコマンドパラメータの取得
|
291
|
+
def get_fd_params(m)
|
292
|
+
adjust_number = m[FD_ADJUST_NUMBER_INDEX].to_i
|
293
|
+
|
294
|
+
opt_params = m[FD_OPTION_START_INDEX..m.length].compact
|
295
|
+
|
296
|
+
return adjust_number, get_options(opt_params)
|
297
|
+
end
|
298
|
+
|
299
|
+
# ================ RGコマンド ================#
|
300
|
+
|
301
|
+
RG_DIFFICULTY_INDEX = 1
|
302
|
+
RG_SUCCESS_DICE_INDEX = 3
|
303
|
+
RG_PIERCING_BLOWS_INDEX = 5
|
304
|
+
RG_ADJUST_NUMBER_INDEX = 7
|
305
|
+
RG_OPTION_START_INDEX = 8
|
306
|
+
|
307
|
+
# RGコマンド実行
|
308
|
+
def rg_command_exec(command)
|
309
|
+
m = /\A(\d+)(RG)(\d*)(@(\d{0,2}))?(A(-?\d*))?([WFIM]-?\d*)?([WFIM]-?\d*)?([WFIM]-?\d*)?([WFIM]-?\d*)?$/.match(command)
|
310
|
+
unless m
|
311
|
+
return ''
|
312
|
+
end
|
313
|
+
|
314
|
+
success_count = 0
|
315
|
+
|
316
|
+
# コマンドパラメータ取得
|
317
|
+
difficulty, success_dice_count, piercing_blows_number, adjust_number, opts = get_rg_params(m)
|
318
|
+
|
319
|
+
# 判定ダイス処理
|
320
|
+
feat_result_text, feat_die_number, feat_dice_count = make_featdice_roll(opts.favoured_state)
|
321
|
+
total_dice_number = (feat_die_number != SAURONS_EYE_NUMBER ? feat_die_number : 0)
|
322
|
+
|
323
|
+
result_header_text = "(#{feat_dice_count}D12"
|
324
|
+
result_dice_text = feat_result_text
|
325
|
+
|
326
|
+
# 技量ダイスが指定されているならその処理
|
327
|
+
if success_dice_count > 0
|
328
|
+
success_result_text, success_total_number, success_count = make_successdice_roll(success_dice_count, opts.weary)
|
329
|
+
total_dice_number += success_total_number
|
330
|
+
|
331
|
+
result_header_text = "#{result_header_text}+#{success_dice_count}D6"
|
332
|
+
result_dice_text = "#{result_dice_text}+#{success_result_text}"
|
333
|
+
end
|
334
|
+
|
335
|
+
# 修正値処理
|
336
|
+
total_dice_number, adjust_number_text = get_rg_adjust(total_dice_number, adjust_number)
|
337
|
+
|
338
|
+
result_header_text = "#{result_header_text}#{adjust_number_text}) > #{result_dice_text}#{adjust_number_text}"
|
339
|
+
|
340
|
+
return get_rg_roll_result(result_header_text, difficulty, feat_die_number, piercing_blows_number, total_dice_number, success_count, opts)
|
341
|
+
end
|
342
|
+
|
343
|
+
# 修正値と修正値テキストの取得
|
344
|
+
def get_rg_adjust(total_dice_number, adjust_number)
|
345
|
+
total_dice_number += adjust_number
|
346
|
+
total_dice_number = 0 if total_dice_number < 0
|
347
|
+
|
348
|
+
return total_dice_number, get_adjust_number_text(adjust_number)
|
349
|
+
end
|
350
|
+
|
351
|
+
# RGコマンド判定結果の取得
|
352
|
+
def get_rg_roll_result(result_header_text, difficulty, feat_die_number, piercing_blows_number, total_dice_number, success_count, opts)
|
353
|
+
# 状態表示取得
|
354
|
+
condition_text = get_condition_text(opts)
|
355
|
+
|
356
|
+
success_count_text = "成功度 #{success_count}"
|
357
|
+
|
358
|
+
# 痛打判定をブロック化
|
359
|
+
piercing_blows = lambda() { |feat_die_num, piercing_blows_num, res_text, cond_text|
|
360
|
+
if piercing_blows_num > 0 && feat_die_num >= piercing_blows_num && feat_die_num != SAURONS_EYE_NUMBER
|
361
|
+
res_text = "#{res_text} 痛打発生!"
|
362
|
+
end
|
363
|
+
return "#{res_text}#{cond_text}"
|
364
|
+
}
|
365
|
+
|
366
|
+
if feat_die_number == GANDALF_RUNE_NUMBER
|
367
|
+
gandalf_rune_text = "#{result_header_text}:自動成功[#{success_count_text}]"
|
368
|
+
gandalf_rune_text = piercing_blows.call(feat_die_number, piercing_blows_number, gandalf_rune_text, condition_text)
|
369
|
+
if success_count >= 2
|
370
|
+
return Result.critical(gandalf_rune_text)
|
371
|
+
end
|
372
|
+
|
373
|
+
return Result.success(gandalf_rune_text)
|
374
|
+
elsif opts.miserable && feat_die_number == SAURONS_EYE_NUMBER
|
375
|
+
return Result.failure("#{result_header_text}:自動失敗#{condition_text}")
|
376
|
+
end
|
377
|
+
|
378
|
+
result_detail_text = "難易度 #{difficulty} 達成値 #{total_dice_number}"
|
379
|
+
if difficulty > total_dice_number
|
380
|
+
return Result.failure("#{result_header_text} #{result_detail_text}:失敗#{condition_text}")
|
381
|
+
end
|
382
|
+
|
383
|
+
success_text = "#{result_header_text} #{result_detail_text}:成功[#{success_count_text}]"
|
384
|
+
success_text = piercing_blows.call(feat_die_number, piercing_blows_number, success_text, condition_text)
|
385
|
+
if success_count >= 2
|
386
|
+
return Result.critical(success_text)
|
387
|
+
end
|
388
|
+
|
389
|
+
return Result.success(success_text)
|
390
|
+
end
|
391
|
+
|
392
|
+
# RGコマンドパラメータの取得
|
393
|
+
def get_rg_params(m)
|
394
|
+
difficulty = m[RG_DIFFICULTY_INDEX].to_i
|
395
|
+
|
396
|
+
success_dice_count = m[RG_SUCCESS_DICE_INDEX].to_i
|
397
|
+
adjust_number = m[RG_ADJUST_NUMBER_INDEX].to_i
|
398
|
+
piercing_blows_number = m[RG_PIERCING_BLOWS_INDEX]&.to_i || -1 # -1は痛打判定自体を行わない
|
399
|
+
|
400
|
+
opt_params = m[RG_OPTION_START_INDEX..m.length].compact
|
401
|
+
|
402
|
+
return difficulty, success_dice_count, piercing_blows_number, adjust_number, get_options(opt_params)
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BCDice
|
4
|
+
module GameSystem
|
5
|
+
class TheUnofficialHollowKnightRPG < Base
|
6
|
+
# ゲームシステムの識別子
|
7
|
+
ID = 'TheUnofficialHollowKnightRPG'
|
8
|
+
|
9
|
+
# ゲームシステム名
|
10
|
+
NAME = 'The Unofficial Hollow Knight RPG'
|
11
|
+
|
12
|
+
# ゲームシステム名の読みがな
|
13
|
+
SORT_KEY = 'しあんおふいしやるほろうないとRPG'
|
14
|
+
|
15
|
+
# ダイスボットの使い方
|
16
|
+
HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
|
17
|
+
・能力値判定 [n]AD[+b][#r][>=t]
|
18
|
+
n: 能力値。小数可。省略不可。
|
19
|
+
b: ボーナス、ペナルティダイス。省略可。
|
20
|
+
r: 追加リロールダイス数。省略可。
|
21
|
+
t: 目標値。>=含めて省略可。
|
22
|
+
成功数を判定。
|
23
|
+
例)1AD, 2.5AD, 1.5AD+1, 2AD#1, 2.5AD+2#2>=4
|
24
|
+
|
25
|
+
・イニシアチブ [n]INTI[+b][#r]
|
26
|
+
n: イニシアチブに使う能力値。省略不可。
|
27
|
+
b: ボーナス、ペナルティダイス。省略可。
|
28
|
+
r: 追加リロールダイス数。省略可。
|
29
|
+
振り直しを行ったうえでイニシアチブ値を計算。
|
30
|
+
例)1INTI, 2.5INTI, 1.5INTI+1, 2INTI#1, 2.5INTI+2#2
|
31
|
+
INFO_MESSAGE_TEXT
|
32
|
+
|
33
|
+
register_prefix('(\d+\.?\d*)?AD([+-](\d+))?(#(\d+))?(>=(\d+))?', '(\d+\.?\d*)?(INTI|inti)([+-](\d+))?(#(\d+))?')
|
34
|
+
|
35
|
+
def initialize(command)
|
36
|
+
super(command)
|
37
|
+
|
38
|
+
@sort_barabara_dice = false # バラバラロール(Bコマンド)でソート無
|
39
|
+
end
|
40
|
+
|
41
|
+
def eval_game_system_specific_command(command)
|
42
|
+
ability_roll(command) || initiative_roll(command)
|
43
|
+
end
|
44
|
+
|
45
|
+
def number_with_sign_from_int(number)
|
46
|
+
if number == 0
|
47
|
+
return ""
|
48
|
+
elsif number > 0
|
49
|
+
return "+#{number.abs}"
|
50
|
+
elsif number < 0
|
51
|
+
return "-#{number.abs}"
|
52
|
+
else
|
53
|
+
return number.to_s
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def number_with_reroll_from_int(number)
|
58
|
+
if number == 0
|
59
|
+
return ""
|
60
|
+
elsif number > 0
|
61
|
+
return "\##{number}"
|
62
|
+
else
|
63
|
+
return number.to_s
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# 能力値ロール
|
68
|
+
def ability_roll(command)
|
69
|
+
m = /^(\d+\.?\d*)?AD([+-](\d+))?(#(\d*))?(>=(\d+))?/.match(command)
|
70
|
+
unless m
|
71
|
+
return nil
|
72
|
+
end
|
73
|
+
|
74
|
+
num_of_die = m[1].to_f
|
75
|
+
bonus = m[3].to_i
|
76
|
+
reroll = m[5].to_i
|
77
|
+
difficulty = m[7].to_i
|
78
|
+
|
79
|
+
if /\.[1-9]+/ =~ num_of_die.to_s
|
80
|
+
dice_command = "#{num_of_die}AD#{number_with_sign_from_int(bonus)}#{number_with_reroll_from_int(reroll)}"
|
81
|
+
reroll += 1
|
82
|
+
else
|
83
|
+
dice_command = "#{num_of_die.to_i}AD#{number_with_sign_from_int(bonus)}#{number_with_reroll_from_int(reroll)}"
|
84
|
+
end
|
85
|
+
|
86
|
+
if difficulty == 0
|
87
|
+
difficulty = 5
|
88
|
+
else
|
89
|
+
dice_command += ">=#{difficulty}"
|
90
|
+
end
|
91
|
+
|
92
|
+
# 振られたダイスを入れる
|
93
|
+
values = @randomizer.roll_barabara(num_of_die.to_i + bonus, 6)
|
94
|
+
# 成功数
|
95
|
+
result = values.count { |num| num >= difficulty }
|
96
|
+
failed_roll = num_of_die.to_i - result
|
97
|
+
|
98
|
+
# ロールの結果の文字列
|
99
|
+
rolled_text = "[" + values.join(",") + "]"
|
100
|
+
|
101
|
+
reroll_values = []
|
102
|
+
|
103
|
+
if reroll == 1
|
104
|
+
reroll_values.push(@randomizer.roll_once(6))
|
105
|
+
elsif reroll > 1
|
106
|
+
reroll_values += @randomizer.roll_barabara(reroll, 6)
|
107
|
+
end
|
108
|
+
|
109
|
+
reroll_result = reroll_values.count { |num| num >= difficulty }
|
110
|
+
if failed_roll < reroll_result
|
111
|
+
reroll_result = failed_roll
|
112
|
+
end
|
113
|
+
result += reroll_result
|
114
|
+
|
115
|
+
# リロールの結果の文字列をロールの結果の文字列に追加する
|
116
|
+
unless reroll_values.empty?
|
117
|
+
rolled_text += " Reroll [" + reroll_values.join(",") + "]"
|
118
|
+
end
|
119
|
+
|
120
|
+
# 結果
|
121
|
+
return "(#{dice_command}) > #{rolled_text} > #{result}成功"
|
122
|
+
end
|
123
|
+
|
124
|
+
# イニシアチブロール
|
125
|
+
def initiative_roll(command)
|
126
|
+
m = /^(\d+\.?\d*)?(INTI|inti)([+-](\d+))?(#(\d+))?/.match(command)
|
127
|
+
unless m
|
128
|
+
return nil
|
129
|
+
end
|
130
|
+
|
131
|
+
grace = m[1].to_f
|
132
|
+
bonus = m[3].to_i
|
133
|
+
reroll = m[6].to_i
|
134
|
+
|
135
|
+
if /\.[1-9]+/ =~ grace.to_s
|
136
|
+
dice_command = "(#{grace}INTI#{number_with_sign_from_int(bonus)}#{number_with_reroll_from_int(reroll)})"
|
137
|
+
reroll += 1
|
138
|
+
else
|
139
|
+
dice_command = "(#{grace.to_i}INTI#{number_with_sign_from_int(bonus)}#{number_with_reroll_from_int(reroll)})"
|
140
|
+
end
|
141
|
+
|
142
|
+
values = @randomizer.roll_barabara(grace + bonus, 6)
|
143
|
+
|
144
|
+
revalue = []
|
145
|
+
unless reroll == 0
|
146
|
+
revalue = @randomizer.roll_barabara(reroll, 6)
|
147
|
+
end
|
148
|
+
revalue = revalue.sort
|
149
|
+
|
150
|
+
result = 0
|
151
|
+
|
152
|
+
res_text = "["
|
153
|
+
values.each do |value|
|
154
|
+
if revalue.empty? # リロールがなければ
|
155
|
+
res_text += value.to_s
|
156
|
+
result += value
|
157
|
+
else # リロールがあったら
|
158
|
+
is_min = false
|
159
|
+
index = -1
|
160
|
+
revalue.each do |re|
|
161
|
+
index += 1
|
162
|
+
next unless re > value # リロールしたダイス最小値か
|
163
|
+
|
164
|
+
res_text += "#{value}<<#{re}"
|
165
|
+
result += re
|
166
|
+
revalue.delete_at(index)
|
167
|
+
is_min = true
|
168
|
+
break
|
169
|
+
end
|
170
|
+
unless is_min # 最小値でなかったら
|
171
|
+
res_text += value.to_s
|
172
|
+
result += value
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
res_text += ","
|
177
|
+
end
|
178
|
+
res_text = res_text.chop
|
179
|
+
res_text += "]"
|
180
|
+
|
181
|
+
return "#{dice_command} > #{res_text} > #{result}"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -31,6 +31,11 @@ module BCDice
|
|
31
31
|
mはポシビリティを使用する前のロール結果を入れて下さい。
|
32
32
|
出目が10未満の場合は、10への読み替えが行われます。
|
33
33
|
また、振り足しを自動で行い、20の出目が出たときには技能無し値も並記します。
|
34
|
+
・CPOS
|
35
|
+
"CPOSm"で、コズムポシビリティ使用による1d20のロールを行います。
|
36
|
+
mはポシビリティを使用する前のロール結果を入れて下さい。
|
37
|
+
出目が10未満の場合でも、10への読み替えが行われません。
|
38
|
+
振り足しは自動で行い、20の出目が出たときには技能無し値も並記します。
|
34
39
|
・ボーナスダメージロール
|
35
40
|
"xBD[+y]"でロールします。[]内は省略可能。
|
36
41
|
xはダメージダイス数。yはダメージ基本値 or 式を入れて下さい。
|
@@ -42,13 +47,14 @@ module BCDice
|
|
42
47
|
・ダメージ結果表「DTx or DAMAGEx」
|
43
48
|
・ロールボーナス表「BTx+y or BONUSx+y or TOTALx+y」 xは数値, yは技能基本値
|
44
49
|
INFO_MESSAGE_TEXT
|
45
|
-
register_prefix('TE', 'UP', 'POS', '\d+BD', 'TG', 'RT', 'Result', 'DT', 'damage', 'BT', 'bonus', 'total', '1R20')
|
50
|
+
register_prefix('TE', 'UP', 'POS', 'CPOS', '\d+BD', 'TG', 'RT', 'Result', 'DT', 'damage', 'BT', 'bonus', 'total', '1R20')
|
46
51
|
|
47
52
|
def eval_game_system_specific_command(command)
|
48
53
|
torg_check(command) ||
|
49
54
|
getRolld20DiceCommandResult(command) ||
|
50
55
|
getUpRollDiceCommandResult(command) ||
|
51
56
|
getPossibilityRollDiceCommandResult(command) ||
|
57
|
+
getCosmPossibilityRollDiceCommandResult(command) ||
|
52
58
|
getBonusDamageDiceCommandResult(command) ||
|
53
59
|
getSuccessLevelDiceCommandResult(command) ||
|
54
60
|
getDamageResultDiceCommandResult(command) ||
|
@@ -75,7 +81,7 @@ module BCDice
|
|
75
81
|
mod = m[1]
|
76
82
|
|
77
83
|
debug(mod)
|
78
|
-
mod =
|
84
|
+
mod = mod ? Arithmetic.eval(mod, @round_type) : 0
|
79
85
|
debug(mod)
|
80
86
|
mod = mod.to_i
|
81
87
|
skilled, unskilled, dice_str, = torg_eternity_dice(false, false)
|
@@ -191,7 +197,7 @@ module BCDice
|
|
191
197
|
return nil
|
192
198
|
end
|
193
199
|
|
194
|
-
output_modifier =
|
200
|
+
output_modifier = m[1] ? Arithmetic.eval(m[1], @round_type) : 0
|
195
201
|
skilled, unskilled, dice_str, = torg_eternity_dice(true, false)
|
196
202
|
subtotal_skilled = skilled + output_modifier
|
197
203
|
subtotal_unskilled = unskilled + output_modifier
|
@@ -206,6 +212,29 @@ module BCDice
|
|
206
212
|
return output
|
207
213
|
end
|
208
214
|
|
215
|
+
# ロールコマンド (コズムポシビリティロール)
|
216
|
+
def getCosmPossibilityRollDiceCommandResult(command)
|
217
|
+
debug("Torg Eternity CosmPossibility Roll Command ? ", command)
|
218
|
+
m = /^CPOS((\d+)(\+\d+)?)$/i.match(command)
|
219
|
+
unless m
|
220
|
+
return nil
|
221
|
+
end
|
222
|
+
|
223
|
+
output_modifier = m[1] ? Arithmetic.eval(m[1], @round_type) : 0
|
224
|
+
skilled, unskilled, dice_str, = torg_eternity_dice(false, false)
|
225
|
+
subtotal_skilled = skilled + output_modifier
|
226
|
+
subtotal_unskilled = unskilled + output_modifier
|
227
|
+
value_skilled = format("%+d", get_torg_eternity_bonus(subtotal_skilled))
|
228
|
+
if subtotal_skilled != subtotal_unskilled
|
229
|
+
value_unskilled = format("%+d", get_torg_eternity_bonus(subtotal_unskilled))
|
230
|
+
output = "d20ロール(ポシビリティ) > #{output_modifier}+1d20[#{dice_str}] > #{value_skilled}[#{subtotal_skilled}](技能有) / #{value_unskilled}[#{subtotal_unskilled}](技能無)"
|
231
|
+
else
|
232
|
+
output = "d20ロール(ポシビリティ) > #{output_modifier}+1d20[#{dice_str}] > #{value_skilled}[#{subtotal_skilled}]"
|
233
|
+
end
|
234
|
+
|
235
|
+
return output
|
236
|
+
end
|
237
|
+
|
209
238
|
# ダメージボーナスコマンド
|
210
239
|
def getBonusDamageDiceCommandResult(command)
|
211
240
|
debug("TorgEternity Bonus Damage Roll Command ? ", command)
|
@@ -234,7 +263,7 @@ module BCDice
|
|
234
263
|
return nil
|
235
264
|
end
|
236
265
|
|
237
|
-
value =
|
266
|
+
value = m[2] ? Arithmetic.eval(m[2], @round_type) : 0
|
238
267
|
debug(value)
|
239
268
|
if value < 0
|
240
269
|
output = "Failure."
|
@@ -254,7 +283,7 @@ module BCDice
|
|
254
283
|
return nil
|
255
284
|
end
|
256
285
|
|
257
|
-
value =
|
286
|
+
value = m[2] ? Arithmetic.eval(m[2], @round_type) : 0
|
258
287
|
debug(value)
|
259
288
|
output = get_torg_eternity_damage_result(value)
|
260
289
|
output = "ダメージ結果表[#{value}] > #{output}"
|
@@ -307,7 +336,7 @@ module BCDice
|
|
307
336
|
value_modifier = 0
|
308
337
|
output_modifier = ""
|
309
338
|
else
|
310
|
-
value_modifier =
|
339
|
+
value_modifier = string_modifier ? Arithmetic.eval(string_modifier, @round_type) : 0
|
311
340
|
output_modifier = format("%+d", value_modifier)
|
312
341
|
end
|
313
342
|
debug(value_modifier)
|