bcdice 3.13.0 → 3.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +45 -0
- data/i18n/Arianrhod/ko_kr.yml +3 -0
- data/i18n/Cthulhu/en_us.yml +11 -0
- data/i18n/CyberpunkRed/ja_jp.yml +389 -0
- data/i18n/FinalFantasyXIV/en_us.yml +4 -0
- data/i18n/FinalFantasyXIV/ja_jp.yml +4 -0
- data/i18n/FutariSousa/ja_jp.yml +158 -1
- data/i18n/KizunaBullet/ja_jp.yml +653 -0
- data/i18n/MonotoneMuseum/ja_jp.yml +246 -14
- data/i18n/SkynautsBouken/ja_jp.yml +114 -0
- 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/lib/bcdice/dice_table/range_table.rb +24 -0
- data/lib/bcdice/game_system/Agnostos.rb +248 -0
- data/lib/bcdice/game_system/AniMalus.rb +99 -59
- data/lib/bcdice/game_system/Arianrhod_Korean.rb +30 -0
- data/lib/bcdice/game_system/BlackJacket.rb +244 -0
- data/lib/bcdice/game_system/ConvictorDrive.rb +5 -4
- data/lib/bcdice/game_system/Cthulhu_English.rb +59 -0
- data/lib/bcdice/game_system/CyberpunkRed.rb +14 -4
- data/lib/bcdice/game_system/DivineCharger.rb +841 -0
- 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 +39 -10
- data/lib/bcdice/game_system/FutariSousa.rb +88 -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/KizunaBullet.rb +240 -0
- data/lib/bcdice/game_system/KyokoShinshoku.rb +51 -8
- data/lib/bcdice/game_system/MonotoneMuseum.rb +14 -1
- data/lib/bcdice/game_system/NRR.rb +2 -2
- data/lib/bcdice/game_system/ShuumatsuBargainWars.rb +203 -0
- data/lib/bcdice/game_system/SkynautsBouken.rb +45 -130
- data/lib/bcdice/game_system/SwordWorld.rb +1 -1
- data/lib/bcdice/game_system/TensaiGunshiNiNaro.rb +228 -0
- data/lib/bcdice/game_system/TheOneRing2nd.rb +406 -0
- data/lib/bcdice/game_system/TheUnofficialHollowKnightRPG.rb +185 -0
- 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/Yotabana.rb +62 -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.rb +16 -0
- data/lib/bcdice/version.rb +1 -1
- metadata +30 -2
@@ -0,0 +1,240 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bcdice/game_system/kizuna_bullet/tables"
|
4
|
+
|
5
|
+
module BCDice
|
6
|
+
module GameSystem
|
7
|
+
class KizunaBullet < Base
|
8
|
+
# ゲームシステムの識別子
|
9
|
+
ID = 'KizunaBullet'
|
10
|
+
|
11
|
+
# ゲームシステム名
|
12
|
+
NAME = 'キズナバレット'
|
13
|
+
|
14
|
+
# ゲームシステム名の読みがな
|
15
|
+
SORT_KEY = 'きすなはれつと'
|
16
|
+
|
17
|
+
# ダイスボットの使い方
|
18
|
+
HELP_MESSAGE = <<~MESSAGETEXT
|
19
|
+
・ダイスロール
|
20
|
+
nDM…n個の6面ダイスを転がして、一番高い出目を採用します。
|
21
|
+
・[調査判定]
|
22
|
+
nIN…n個の6面ダイスを転がして、一番高い出目が5以上なら成功します。([パートナーのヘルプ]使用可)
|
23
|
+
・[鎮静判定]
|
24
|
+
SEn…2個の6面ダイスを転がして、出目の合計値がn([ヒビワレ]状態の[キズナ]の個数)より高いと成功します。([強制鎮静]使用可)
|
25
|
+
・[解決] [アクション]のダメージと[アクシデント]のダメージ軽減
|
26
|
+
nSO…2+n個の6面ダイスを転がして、出目をすべて合計します。(nは減らした【励起値】。省略可能)
|
27
|
+
・各種表
|
28
|
+
日常表・場所 OP
|
29
|
+
日常表・内容 OC
|
30
|
+
日常表・場所と内容 OPC
|
31
|
+
日常表(仕事)・場所 OWP
|
32
|
+
日常表(仕事)・内容 OWC
|
33
|
+
日常表(仕事)・場所と内容 OWPC
|
34
|
+
日常表(休暇)・場所 OHP
|
35
|
+
日常表(休暇)・内容 OHC
|
36
|
+
日常表(休暇)・場所と内容 OHPC
|
37
|
+
日常表(出張)・場所 OTP
|
38
|
+
日常表(出張)・内容 OTC
|
39
|
+
日常表(出張)・場所と内容 OTPC
|
40
|
+
ターンテーマ表 TT
|
41
|
+
ターンテーマ表・親密 TTI
|
42
|
+
ターンテーマ表・クール TTC
|
43
|
+
ターンテーマ表・主従 TTH
|
44
|
+
遭遇表・場所 EP
|
45
|
+
遭遇表・登場順 EO
|
46
|
+
遭遇表・状況(初対面) EF
|
47
|
+
遭遇表・状況(知り合い) EA
|
48
|
+
遭遇表・決着 EE
|
49
|
+
遭遇表・場所と登場順と状況(初対面)と決着 EFA
|
50
|
+
遭遇表・場所と登場順と状況(知り合い)と決着 EAA
|
51
|
+
交流表・場所 CP
|
52
|
+
交流表・内容 CC
|
53
|
+
交流表・場所と内容 CPC
|
54
|
+
調査表・ベーシック IB
|
55
|
+
調査表・ダイナミック ID
|
56
|
+
調査表・ベーシックとダイナミック IBD
|
57
|
+
ハザード表 HA
|
58
|
+
通常ダイジェスト キミたちに新しい命令が下った(調査が依頼された)。
|
59
|
+
1:その事件の内容は…… NI1
|
60
|
+
2:捜査に向かった場所は…… NI2
|
61
|
+
3:犯人のキセキ使いは…… NI3
|
62
|
+
4:起きた出来事は…… NI4
|
63
|
+
5:バレットの間では…… NI5
|
64
|
+
6:戦いの結末は…… NI6
|
65
|
+
通常ダイジェスト キミたちは旅行(出張)である場所を訪れた。
|
66
|
+
1:その場所とは…… NT1
|
67
|
+
2:そこで始まったのは…… NT2
|
68
|
+
3:極限状態のなかで…… NT3
|
69
|
+
4:犯人のキセキ使いは…… NT4
|
70
|
+
5:バレットの間では…… NT5
|
71
|
+
6:戦いの結末は…… NT6
|
72
|
+
ホリデーダイジェスト キミたちは休日に出かけることにした。
|
73
|
+
1:その場所とは…… HH1
|
74
|
+
2:待ち合わせをしたら…… HH2
|
75
|
+
3:そしてなんと…… HH3
|
76
|
+
4:ふたりが決めたのは…… HH4
|
77
|
+
5:結果的に…… HH5
|
78
|
+
6:バレットは最後に…… HH6
|
79
|
+
ホリデーダイジェスト キミたちは奇妙な事件に出くわした。
|
80
|
+
1:その場所とは…… HC1
|
81
|
+
2:起きた事件は…… HC2
|
82
|
+
3:犯人のキセキ使いは…… HC3
|
83
|
+
4:犯人を追い詰めるべく…… HC4
|
84
|
+
5:戦いの結果は…… HC5
|
85
|
+
6:バレットは最後に…… HC6
|
86
|
+
MESSAGETEXT
|
87
|
+
|
88
|
+
TABLES = translate_tables(@locale)
|
89
|
+
|
90
|
+
def initialize(command)
|
91
|
+
super(command)
|
92
|
+
|
93
|
+
@sides_implicit_d = 6
|
94
|
+
@round_type = RoundType::CEIL
|
95
|
+
@d66_sort_type = D66SortType::NO_SORT
|
96
|
+
end
|
97
|
+
|
98
|
+
def eval_game_system_specific_command(command)
|
99
|
+
roll_max(command) || roll_investigate(command) || roll_sedative(command) || roll_solve(command) || roll_tables(command, self.class::TABLES)
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
# 最大値
|
105
|
+
def roll_max(command)
|
106
|
+
parser = Command::Parser.new("DM", round_type: @round_type)
|
107
|
+
.has_prefix_number
|
108
|
+
parsed = parser.parse(command)
|
109
|
+
unless parsed
|
110
|
+
return nil
|
111
|
+
end
|
112
|
+
|
113
|
+
# 最大値計算
|
114
|
+
dice_list = @randomizer.roll_barabara(parsed.prefix_number, 6)
|
115
|
+
max = dice_list.max
|
116
|
+
|
117
|
+
return Result.new.tap do |r|
|
118
|
+
# テキストを整形
|
119
|
+
r.text = "#{command} > [#{dice_list.join(',')}] > #{max}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# 調査判定
|
124
|
+
def roll_investigate(command)
|
125
|
+
parser = Command::Parser.new("IN", round_type: @round_type)
|
126
|
+
.has_prefix_number
|
127
|
+
parsed = parser.parse(command)
|
128
|
+
unless parsed
|
129
|
+
return nil
|
130
|
+
end
|
131
|
+
|
132
|
+
texts = []
|
133
|
+
is_success = false
|
134
|
+
is_fumble = false
|
135
|
+
|
136
|
+
# 最大値計算
|
137
|
+
dice_list = @randomizer.roll_barabara(parsed.prefix_number, 6)
|
138
|
+
max = dice_list.max
|
139
|
+
|
140
|
+
if max >= 5
|
141
|
+
# 5以上の出目があった場合
|
142
|
+
# 成功フラグを立てる
|
143
|
+
is_success = true
|
144
|
+
# 成功メッセージを追加
|
145
|
+
texts.push(translate("KizunaBullet.INVESTIGATE.success"))
|
146
|
+
elsif max >= 3
|
147
|
+
# 3以上の出目があった場合
|
148
|
+
# 失敗メッセージを追加
|
149
|
+
texts.push(translate("KizunaBullet.INVESTIGATE.failure"))
|
150
|
+
# [パートナーのヘルプ]メッセージを追加
|
151
|
+
texts.push(translate("KizunaBullet.INVESTIGATE.partnerHelp"))
|
152
|
+
else
|
153
|
+
# 上記以外
|
154
|
+
# ファンブルフラグを立てる
|
155
|
+
is_fumble = true
|
156
|
+
# 失敗メッセージを追加
|
157
|
+
texts.push(translate("KizunaBullet.INVESTIGATE.failure"))
|
158
|
+
# ファンブルメッセージを追加
|
159
|
+
texts.push(translate("KizunaBullet.INVESTIGATE.fumble"))
|
160
|
+
end
|
161
|
+
|
162
|
+
return Result.new.tap do |r|
|
163
|
+
# テキストを整形
|
164
|
+
r.text = "#{command} > [#{dice_list.join(',')}] > #{texts.join('')}"
|
165
|
+
# 各種成否を格納
|
166
|
+
r.condition = is_success
|
167
|
+
r.fumble = is_fumble
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# 鎮静判定
|
172
|
+
def roll_sedative(command)
|
173
|
+
parser = Command::Parser.new("SE", round_type: @round_type)
|
174
|
+
.has_suffix_number
|
175
|
+
parsed = parser.parse(command)
|
176
|
+
unless parsed
|
177
|
+
return nil
|
178
|
+
end
|
179
|
+
|
180
|
+
text = ''
|
181
|
+
is_success = false
|
182
|
+
|
183
|
+
# 合計値計算
|
184
|
+
sum = @randomizer.roll_sum(2, 6)
|
185
|
+
|
186
|
+
if parsed.suffix_number > 12
|
187
|
+
# 目標値が12より大きい場合
|
188
|
+
# [晶滅]メッセージを追加
|
189
|
+
text = translate("KizunaBullet.SEDATIVE.burst")
|
190
|
+
elsif parsed.suffix_number < 6
|
191
|
+
# 目標値が6より小さい場合
|
192
|
+
# [生存]メッセージを追加
|
193
|
+
text = translate("KizunaBullet.SEDATIVE.alive")
|
194
|
+
elsif sum > parsed.suffix_number
|
195
|
+
# 合計値が目標値より大きい場合
|
196
|
+
# 成功フラグを立てる
|
197
|
+
is_success = true
|
198
|
+
# 成功メッセージを追加
|
199
|
+
text = translate("KizunaBullet.SEDATIVE.success")
|
200
|
+
else
|
201
|
+
# 上記以外
|
202
|
+
# [強制鎮静]に必要な[キズナ]のチェック数の計算
|
203
|
+
# 目標値と出目の差分を計算
|
204
|
+
dif = parsed.suffix_number - sum
|
205
|
+
# チェック一つごとに結果に+2
|
206
|
+
check = (dif / 2) + 1
|
207
|
+
# 失敗メッセージを追加
|
208
|
+
text = translate("KizunaBullet.SEDATIVE.failure", check: check.to_s)
|
209
|
+
end
|
210
|
+
|
211
|
+
return Result.new.tap do |r|
|
212
|
+
# テキストを整形
|
213
|
+
r.text = "#{command} > #{sum} > #{text}"
|
214
|
+
# 各種成否を格納
|
215
|
+
r.condition = is_success
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# 解決 [アクション]のダメージと[アクシデント]のダメージ軽減
|
220
|
+
def roll_solve(command)
|
221
|
+
parser = Command::Parser.new("SO", round_type: @round_type)
|
222
|
+
.enable_prefix_number
|
223
|
+
parsed = parser.parse(command)
|
224
|
+
unless parsed
|
225
|
+
return nil
|
226
|
+
end
|
227
|
+
|
228
|
+
# 合計値計算
|
229
|
+
sum = @randomizer.roll_sum(parsed.prefix_number.to_i + 2, 6)
|
230
|
+
|
231
|
+
return Result.new.tap do |r|
|
232
|
+
# テキストを整形
|
233
|
+
r.text = "#{command} > #{sum}"
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
register_prefix('\d+DM', '\d+IN', 'SE\d+', '\d*SO', TABLES.keys)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
@@ -15,7 +15,7 @@ module BCDice
|
|
15
15
|
# ダイスボットの使い方
|
16
16
|
HELP_MESSAGE = <<~MESSAGETEXT
|
17
17
|
・判定
|
18
|
-
|
18
|
+
ダイスを指定数ダイスロールして、最も高い出目を出力します。難易度を指定すると成否を判定します。オプションでA、Dをつけると、[有利][不利]の条件で振れます(A=[有利]、D=[不利])。
|
19
19
|
KS(x,y)
|
20
20
|
x:ダイスサイズ。1=D4(能力値1、2以上の出目が出ていたとしても最大1)/2=D4(能力値2、3以上の出目が出ていたとしても最大2)/3=D4(能力値3、出目4が出ていたとしても最大3)/4=D4/6=D6/8=D8/10=D10/12=D12/20=D20
|
21
21
|
y:ダイス数(省略:1)
|
@@ -25,6 +25,16 @@ module BCDice
|
|
25
25
|
y:ダイス数(省略:1)
|
26
26
|
z:難易度
|
27
27
|
|
28
|
+
KS(x,y)A>=z([有利]:KS(x,y)の判定を2回行い、それぞれの結果のより大きい方が結果となります)
|
29
|
+
x:ダイスサイズ。1=D4(能力値1、2以上の出目が出ていたとしても最大1)/2=D4(能力値2、3以上の出目が出ていたとしても最大2)/3=D4(能力値3、出目4が出ていたとしても最大3)/4=D4/6=D6/8=D8/10=D10/12=D12/20=D20
|
30
|
+
y:ダイス数(省略:1)
|
31
|
+
z:難易度
|
32
|
+
|
33
|
+
KS(x,y)D>=z([不利]:KS(x,y)の判定を2回行い、それぞれの結果のより小さい方が結果となります)
|
34
|
+
x:ダイスサイズ。1=D4(能力値1、2以上の出目が出ていたとしても最大1)/2=D4(能力値2、3以上の出目が出ていたとしても最大2)/3=D4(能力値3、出目4が出ていたとしても最大3)/4=D4/6=D6/8=D8/10=D10/12=D12/20=D20
|
35
|
+
y:ダイス数(省略:1)
|
36
|
+
z:難易度
|
37
|
+
|
28
38
|
・観測ロール
|
29
39
|
[現実乖離]の段階に応じたダイスを指定数ダイスロールして、最も高い出目を出力します。
|
30
40
|
KR(x)
|
@@ -62,19 +72,30 @@ module BCDice
|
|
62
72
|
}.freeze
|
63
73
|
|
64
74
|
def roll_check(command)
|
65
|
-
m = /^KS(?:\((
|
75
|
+
m = /^KS(?:\(([-+\d]+),([-+\d]+)?\)|(\d+))([AD]?)(?:>=([-+\d]+))?$/.match(command)
|
66
76
|
return nil unless m
|
67
77
|
|
68
|
-
dice_size = m[1]
|
78
|
+
dice_size = m[1] ? Arithmetic.eval(m[1], @round_type) : Arithmetic.eval(m[3], @round_type).to_i
|
69
79
|
times = m[2] ? Arithmetic.eval(m[2], @round_type) : 1
|
70
|
-
target = m[
|
80
|
+
target = m[5] && Arithmetic.eval(m[5], @round_type)
|
81
|
+
|
82
|
+
advantage = m[4]
|
71
83
|
|
72
84
|
sides = DICE_SIZE_TO_SIDES[dice_size]
|
73
85
|
|
74
86
|
return nil if sides.nil? || times.nil?
|
75
87
|
|
76
|
-
|
77
|
-
|
88
|
+
rolls = Array.new(advantage.empty? ? 1 : 2) { roll_check_once(times, dice_size, sides) }
|
89
|
+
values = rolls.map { |v| v[:value] }
|
90
|
+
|
91
|
+
value =
|
92
|
+
if advantage == "A"
|
93
|
+
values.max
|
94
|
+
elsif advantage == "D"
|
95
|
+
values.min
|
96
|
+
else
|
97
|
+
values.first
|
98
|
+
end
|
78
99
|
|
79
100
|
result =
|
80
101
|
if value == 1
|
@@ -90,8 +111,8 @@ module BCDice
|
|
90
111
|
end
|
91
112
|
|
92
113
|
result.text = [
|
93
|
-
target ? "(KS(#{dice_size},#{times})>=#{target})" : "(KS(#{dice_size},#{times}))",
|
94
|
-
(
|
114
|
+
target ? "(KS(#{dice_size},#{times})#{advantage}>=#{target})" : "(KS(#{dice_size},#{times})#{advantage})",
|
115
|
+
format_rolls(rolls),
|
95
116
|
value,
|
96
117
|
result.text,
|
97
118
|
].compact.join(" > ")
|
@@ -99,6 +120,28 @@ module BCDice
|
|
99
120
|
return result
|
100
121
|
end
|
101
122
|
|
123
|
+
def roll_check_once(times, dice_size, sides)
|
124
|
+
if times < 1
|
125
|
+
dice_list = @randomizer.roll_barabara(2, sides).sort
|
126
|
+
value = dice_list.min.clamp(1, dice_size)
|
127
|
+
else
|
128
|
+
dice_list = @randomizer.roll_barabara(times, sides).sort
|
129
|
+
value = dice_list.max.clamp(1, dice_size)
|
130
|
+
end
|
131
|
+
|
132
|
+
return {dice_list: dice_list, value: value}
|
133
|
+
end
|
134
|
+
|
135
|
+
def format_rolls(rolls)
|
136
|
+
if rolls.length == 1 && rolls.first[:dice_list].length == 1
|
137
|
+
return nil
|
138
|
+
end
|
139
|
+
|
140
|
+
rolls.map do |v|
|
141
|
+
v[:dice_list].length == 1 ? v[:value].to_s : "#{v[:value]}[#{v[:dice_list].join(',')}]"
|
142
|
+
end.join(", ")
|
143
|
+
end
|
144
|
+
|
102
145
|
GENJITU_KAIRI_TO_SIDES = [4, 6, 8, 10, 12, 20].freeze
|
103
146
|
REALITY_LINE_TO_TIMES = {
|
104
147
|
3 => 1,
|
@@ -25,9 +25,16 @@ module BCDice
|
|
25
25
|
クリティカル値、ファンブル値は省略可能です。([]ごと省略できます)
|
26
26
|
自動成功、自動失敗、成功、失敗を自動表示します。
|
27
27
|
・各種表
|
28
|
+
【改訂版環境】
|
29
|
+
・感情表 MET
|
30
|
+
・兆候表(戦闘時) MBOT/兆候表(非戦闘時) MNOT
|
31
|
+
・歪み表 MDT
|
32
|
+
・世界歪曲表 MWDT
|
33
|
+
・永劫消失表 MEDT
|
34
|
+
【旧版環境】
|
28
35
|
・感情表 ET/感情表 2.0 ET2
|
29
36
|
・兆候表 OT/兆候表ver2.0 OT2/兆候表ver3.0 OT3
|
30
|
-
・歪み表 DT/歪み表ver2.0 DT2
|
37
|
+
・歪み表 DT/歪み表ver2.0 DT2/歪み表(野外) DTO/歪み表(海) DTS/歪み表(館・城) DTM
|
31
38
|
・世界歪曲表 WDT/世界歪曲表2.0 WDT2
|
32
39
|
・永劫消失表 EDT
|
33
40
|
・D66ダイスあり
|
@@ -146,6 +153,12 @@ module BCDice
|
|
146
153
|
"EDT" => DiceTable::Table.from_i18n("MonotoneMuseum.table.EDT", locale),
|
147
154
|
"DTM" => MMTable.from_i18n("MonotoneMuseum.table.DTM", locale),
|
148
155
|
"OT3" => DiceTable::Table.from_i18n("MonotoneMuseum.table.OT3", locale),
|
156
|
+
"MET" => DiceTable::D66GridTable.from_i18n("MonotoneMuseum.table.MET", locale),
|
157
|
+
"MBOT" => DiceTable::Table.from_i18n("MonotoneMuseum.table.MBOT", locale),
|
158
|
+
"MNOT" => DiceTable::Table.from_i18n("MonotoneMuseum.table.MNOT", locale),
|
159
|
+
"MDT" => MMTable.from_i18n("MonotoneMuseum.table.MDT", locale),
|
160
|
+
"MWDT" => DiceTable::Table.from_i18n("MonotoneMuseum.table.MWDT", locale),
|
161
|
+
"MEDT" => DiceTable::Table.from_i18n("MonotoneMuseum.table.MEDT", locale),
|
149
162
|
}
|
150
163
|
end
|
151
164
|
end
|
@@ -97,10 +97,10 @@ module BCDice
|
|
97
97
|
SUCCESSES = [:success, :critical, :miracle].freeze
|
98
98
|
CRITICALS = [:critical, :miracle].freeze
|
99
99
|
|
100
|
-
DISADVANTAGE = [:fumble, :
|
100
|
+
DISADVANTAGE = [:fumble, :failure, :failure, :failure, :success, :success].freeze
|
101
101
|
NORMAL = [:fumble, :failure, :failure, :failure, :success, :success, :success, :critical].freeze
|
102
102
|
ADVANTAGE = [:fumble, :failure, :failure, :success, :success, :success, :success, :success, :critical, :critical].freeze
|
103
|
-
EXTRA = [:fumble, :fumble, :
|
103
|
+
EXTRA = [:fumble, :fumble, :failure, :failure, :success, :success, :critical, :critical, :critical, :critical, :miracle, :miracle].freeze
|
104
104
|
|
105
105
|
ICON = {
|
106
106
|
fumble: "💀",
|
@@ -0,0 +1,203 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BCDice
|
4
|
+
module GameSystem
|
5
|
+
class ShuumatsuBargainWars < Base
|
6
|
+
# ゲームシステムの識別子
|
7
|
+
ID = "ShuumatsuBargainWars"
|
8
|
+
|
9
|
+
# ゲームシステム名
|
10
|
+
NAME = "終末買い物戦争"
|
11
|
+
|
12
|
+
# ゲームシステム名の読みがな
|
13
|
+
SORT_KEY = "しゆうまつはあけんうおおす"
|
14
|
+
|
15
|
+
HELP_MESSAGE = <<~TEXT
|
16
|
+
・行為判定 (nBGk+y>=t)n:ダイス数、k:心根、y:修正値(省略可)、t:目標値
|
17
|
+
例)3BG1>=3 2BG3+1>=4 4BG5-1>=3
|
18
|
+
・アイテム表
|
19
|
+
・RT 回復系アイテム表
|
20
|
+
・CT 便利系アイテム表
|
21
|
+
・WT 武器系アイテム表
|
22
|
+
・WG ワゴン(全アイテムランダム)
|
23
|
+
・ET イベント表
|
24
|
+
・TT トラブル表
|
25
|
+
TEXT
|
26
|
+
|
27
|
+
def initialize(command)
|
28
|
+
super(command)
|
29
|
+
@sort_barabara_dice = true
|
30
|
+
@d66_sort_type = D66SortType::ASC
|
31
|
+
end
|
32
|
+
|
33
|
+
RecoveryItemTable = DiceTable::D66Table.new(
|
34
|
+
'回復系アイテム表',
|
35
|
+
D66SortType::ASC,
|
36
|
+
{
|
37
|
+
11 => '飴玉',
|
38
|
+
12 => 'エナジードリンク',
|
39
|
+
13 => 'せんべい',
|
40
|
+
14 => '餅',
|
41
|
+
15 => 'ロウソク',
|
42
|
+
16 => '酒',
|
43
|
+
22 => '寿司',
|
44
|
+
23 => 'ばんそうこう',
|
45
|
+
24 => 'お布団',
|
46
|
+
25 => 'カレー',
|
47
|
+
26 => '消毒液',
|
48
|
+
33 => '缶詰',
|
49
|
+
34 => 'みたらし団子',
|
50
|
+
35 => '骨付き肉',
|
51
|
+
36 => 'ステーキ',
|
52
|
+
44 => 'うちわ',
|
53
|
+
45 => 'ぬいぐるみ',
|
54
|
+
46 => 'のり',
|
55
|
+
55 => '美容液',
|
56
|
+
56 => '黄色いハンカチ',
|
57
|
+
66 => '洗剤',
|
58
|
+
}
|
59
|
+
)
|
60
|
+
|
61
|
+
ConvenienceItemTable = DiceTable::D66Table.new(
|
62
|
+
'便利系アイテム表',
|
63
|
+
D66SortType::ASC,
|
64
|
+
{
|
65
|
+
11 => 'ちくわ',
|
66
|
+
12 => '焼き芋',
|
67
|
+
13 => 'トイレットペーパー',
|
68
|
+
14 => '熊手',
|
69
|
+
15 => '胡椒',
|
70
|
+
16 => '鏡',
|
71
|
+
22 => '割りばし',
|
72
|
+
23 => '輪ゴム',
|
73
|
+
24 => '塩の結晶',
|
74
|
+
25 => 'プチプチマット',
|
75
|
+
26 => '長靴',
|
76
|
+
33 => 'バケツ',
|
77
|
+
34 => 'アルミホイル',
|
78
|
+
35 => '下敷き',
|
79
|
+
36 => '長芋',
|
80
|
+
44 => '鉛筆',
|
81
|
+
45 => 'まな板',
|
82
|
+
46 => 'フライパン',
|
83
|
+
55 => 'ほうき',
|
84
|
+
56 => 'クラッカー',
|
85
|
+
66 => '消臭スプレー',
|
86
|
+
}
|
87
|
+
)
|
88
|
+
|
89
|
+
WeaponItemTable = DiceTable::D66Table.new(
|
90
|
+
'武器系アイテム表',
|
91
|
+
D66SortType::ASC,
|
92
|
+
{
|
93
|
+
11 => 'アズキアイス',
|
94
|
+
12 => 'スプーン',
|
95
|
+
13 => 'フォーク',
|
96
|
+
14 => 'カミソリ',
|
97
|
+
15 => '電池',
|
98
|
+
16 => 'デッキブラシ',
|
99
|
+
22 => '傘',
|
100
|
+
23 => '物干し竿',
|
101
|
+
24 => '鉄パイプ',
|
102
|
+
25 => 'くぎ打ち機',
|
103
|
+
26 => 'モンキーレンチ',
|
104
|
+
33 => 'ハエタタキ',
|
105
|
+
34 => '鎌',
|
106
|
+
35 => '蛍光灯',
|
107
|
+
36 => '包丁',
|
108
|
+
44 => 'ハサミ',
|
109
|
+
45 => 'ショベル',
|
110
|
+
46 => '釣り竿',
|
111
|
+
55 => '芝刈り機',
|
112
|
+
56 => 'ステッキ',
|
113
|
+
66 => '小麦粉',
|
114
|
+
}
|
115
|
+
)
|
116
|
+
|
117
|
+
TABLES = {
|
118
|
+
"ET" => DiceTable::Table.new(
|
119
|
+
"イベント表",
|
120
|
+
"2D6",
|
121
|
+
[
|
122
|
+
"ドッキン!一目惚れ!好きなキャラクターを1人選ぶ。このセッション中その相手との関係の深度を互いに3以上にすることができた場合、シナリオの結末に関係なく貴方は完全無欠のハッピーエンドを迎え経験点を100点得る。達成できなかった場合、エンディングフェイズで目が覚める。",
|
123
|
+
"おや?こんな所にアイテムが転がっている。ランダムに選んだアイテムを獲得する。そのアイテムの種別が支援・計画ならば[技術]/5の判定に成功すれば手番を消費せずそのアイテムを使用しても良い。",
|
124
|
+
"チームメンバーと二人っきりになる。ちょっといい雰囲気かも。好きなキャラクターを目標に選び、『関係』のチェックを外す事ができる。",
|
125
|
+
"あぶな~い!チームメンバーに危機が襲い掛かる。PCの中からランダムに1人を選び[武力]/5の判定を行う。成功すると互いに『関係』を結ぶことができる。失敗すると2人とも体力に1d6点のダメージ。",
|
126
|
+
"ちょっとお食事でも如何?自身の体力3点と活力1点を回復させる。",
|
127
|
+
"穏やかな時が流れる。このメンバーならこれからも上手くやっていけそうだ。ランダムにPCを選び『関係』を獲得する。",
|
128
|
+
"チームメンバーの意外な一面を覗く、まさかアイツあんな趣味があったなんて!PCの中からランダムで1人を選び[精神]/6で判定を行う。成功すると互いに『関係』を獲得する。失敗すると互いに活力が1点減少する。",
|
129
|
+
"仲間と意見が対立する。アイツにだけは負けられない!関係を持つPCの中からランダムで1人を選び、対象との関係の深度を1下げてもよい(0未満にならない)。下げた場合、以降のセッション中任意の能力値が1上昇したものとして判定を行う事ができる。この効果で実際に能力値は上がらない。",
|
130
|
+
"何かお手伝いをしよう。好きなキャラクターを1人選ぶ。この休憩中次に相手が判定を行う場合、その判定に修正値+1を加える。その後、目標は自分に対し『関係』を獲得する。",
|
131
|
+
"酒を発見、宴だぁああ!!!PCは全員回復アイテムの「酒」の効果を使用できる。その後、自分の持つ全ての『関係』をランダムな相手に同じ《深度》で取り直す。",
|
132
|
+
"不味い!敵襲だ!バナナワニにキリミウオが戦闘を仕掛けに来る。戦闘に勝利した場合、好きなアイテムを1つ得る。この処理が面倒ならば戦闘を行う代わりにPC達全員の体力の値を半分にし戦闘に勝利したものとして扱っても良い。"
|
133
|
+
]
|
134
|
+
),
|
135
|
+
"TT" => DiceTable::Table.new(
|
136
|
+
"トラブル表",
|
137
|
+
"1D6",
|
138
|
+
[
|
139
|
+
"緊張感からか焦りが生じる。以降スポットフェイズに行くまでの間あらゆる判定の成功度が1減少する。",
|
140
|
+
"カートの操作が効かなくなった!このラウンドは操作表を全員ダイスを振りランダムで決定する事。",
|
141
|
+
"派手な振動が起き頭をぶつける。全員1d6点のダメージを受ける。",
|
142
|
+
"集中力が切れて来た……全員の活力を1 点減少させる",
|
143
|
+
"激しく揺さぶられ荷物が落下する。カート内にあるアイテムを1 つ選ぶ。そのアイテムを失う。",
|
144
|
+
"不気味な超市場の雰囲気がパッセンジャー達の不安を煽る。特に何も起こらない。",
|
145
|
+
]
|
146
|
+
),
|
147
|
+
"RT" => RecoveryItemTable,
|
148
|
+
"CT" => ConvenienceItemTable,
|
149
|
+
"WT" => WeaponItemTable,
|
150
|
+
"WG" => DiceTable::ChainTable.new(
|
151
|
+
"ワゴン",
|
152
|
+
"1D6",
|
153
|
+
[
|
154
|
+
RecoveryItemTable,
|
155
|
+
RecoveryItemTable,
|
156
|
+
ConvenienceItemTable,
|
157
|
+
ConvenienceItemTable,
|
158
|
+
WeaponItemTable,
|
159
|
+
WeaponItemTable,
|
160
|
+
]
|
161
|
+
),
|
162
|
+
}.freeze
|
163
|
+
|
164
|
+
register_prefix('\d+BG', TABLES.keys)
|
165
|
+
|
166
|
+
def eval_game_system_specific_command(command)
|
167
|
+
return roll_bg(command) || roll_tables(command, TABLES)
|
168
|
+
end
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
def roll_bg(command)
|
173
|
+
parser = Command::Parser.new("BG", round_type: @round_type)
|
174
|
+
.has_prefix_number
|
175
|
+
.has_suffix_number
|
176
|
+
.restrict_cmp_op_to(:>=)
|
177
|
+
parsed = parser.parse(command)
|
178
|
+
return nil unless parsed
|
179
|
+
|
180
|
+
times = parsed.prefix_number
|
181
|
+
kokorone = parsed.suffix_number
|
182
|
+
correction = parsed.modify_number
|
183
|
+
target = parsed.target_number
|
184
|
+
dice_list = @randomizer.roll_barabara(times, 6).sort
|
185
|
+
success = dice_list.count { |number| number >= target - correction }
|
186
|
+
get_vitality = dice_list.count(kokorone)
|
187
|
+
|
188
|
+
result =
|
189
|
+
if dice_list.count(6) >= 2
|
190
|
+
Result.critical("スペシャル! 成功度#{success + 1}、活力#{get_vitality}獲得")
|
191
|
+
elsif dice_list.all?(1)
|
192
|
+
Result.fumble("ファンブル 活力をすべて失う")
|
193
|
+
else
|
194
|
+
Result.new("成功度#{success}、活力#{get_vitality}獲得")
|
195
|
+
end
|
196
|
+
|
197
|
+
result.text = "(#{parsed}) > [#{dice_list.join(',')}] > #{result.text}"
|
198
|
+
|
199
|
+
return result
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|