bcdice 3.13.0 → 3.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +45 -0
  3. data/i18n/Arianrhod/ko_kr.yml +3 -0
  4. data/i18n/Cthulhu/en_us.yml +11 -0
  5. data/i18n/CyberpunkRed/ja_jp.yml +389 -0
  6. data/i18n/FinalFantasyXIV/en_us.yml +4 -0
  7. data/i18n/FinalFantasyXIV/ja_jp.yml +4 -0
  8. data/i18n/FutariSousa/ja_jp.yml +158 -1
  9. data/i18n/KizunaBullet/ja_jp.yml +653 -0
  10. data/i18n/MonotoneMuseum/ja_jp.yml +246 -14
  11. data/i18n/SkynautsBouken/ja_jp.yml +114 -0
  12. data/i18n/TensaiGunshiNiNaro/ja_jp.yml +126 -0
  13. data/i18n/UnsungDuet/ja_jp.yml +62 -0
  14. data/i18n/UnsungDuet/ko_kr.yml +62 -0
  15. data/i18n/en_us.yml +5 -0
  16. data/lib/bcdice/dice_table/range_table.rb +24 -0
  17. data/lib/bcdice/game_system/Agnostos.rb +248 -0
  18. data/lib/bcdice/game_system/AniMalus.rb +99 -59
  19. data/lib/bcdice/game_system/Arianrhod_Korean.rb +30 -0
  20. data/lib/bcdice/game_system/BlackJacket.rb +244 -0
  21. data/lib/bcdice/game_system/ConvictorDrive.rb +5 -4
  22. data/lib/bcdice/game_system/Cthulhu_English.rb +59 -0
  23. data/lib/bcdice/game_system/CyberpunkRed.rb +14 -4
  24. data/lib/bcdice/game_system/DivineCharger.rb +841 -0
  25. data/lib/bcdice/game_system/FinalFantasyXIV.rb +115 -0
  26. data/lib/bcdice/game_system/FinalFantasyXIV_English.rb +39 -0
  27. data/lib/bcdice/game_system/FullFace.rb +39 -10
  28. data/lib/bcdice/game_system/FutariSousa.rb +88 -8
  29. data/lib/bcdice/game_system/Insane_Korean.rb +1 -1
  30. data/lib/bcdice/game_system/InvisibleLiar.rb +79 -0
  31. data/lib/bcdice/game_system/KizunaBullet.rb +240 -0
  32. data/lib/bcdice/game_system/KyokoShinshoku.rb +51 -8
  33. data/lib/bcdice/game_system/MonotoneMuseum.rb +14 -1
  34. data/lib/bcdice/game_system/NRR.rb +2 -2
  35. data/lib/bcdice/game_system/ShuumatsuBargainWars.rb +203 -0
  36. data/lib/bcdice/game_system/SkynautsBouken.rb +45 -130
  37. data/lib/bcdice/game_system/SwordWorld.rb +1 -1
  38. data/lib/bcdice/game_system/TensaiGunshiNiNaro.rb +228 -0
  39. data/lib/bcdice/game_system/TheOneRing2nd.rb +406 -0
  40. data/lib/bcdice/game_system/TheUnofficialHollowKnightRPG.rb +185 -0
  41. data/lib/bcdice/game_system/TrailOfCthulhu.rb +139 -0
  42. data/lib/bcdice/game_system/UnsungDuet.rb +17 -75
  43. data/lib/bcdice/game_system/UnsungDuet_Korean.rb +41 -0
  44. data/lib/bcdice/game_system/Utakaze.rb +55 -2
  45. data/lib/bcdice/game_system/Warhammer4.rb +124 -3
  46. data/lib/bcdice/game_system/Yotabana.rb +62 -0
  47. data/lib/bcdice/game_system/cyberpunk_red/tables.rb +111 -473
  48. data/lib/bcdice/game_system/kizuna_bullet/tables.rb +171 -0
  49. data/lib/bcdice/game_system.rb +16 -0
  50. data/lib/bcdice/version.rb +1 -1
  51. metadata +30 -2
@@ -14,23 +14,23 @@ module BCDice
14
14
 
15
15
  # ダイスボットの使い方
16
16
  HELP_MESSAGE = <<~INFO_MESSAGETEXT
17
- ■ステータスのダイス判定 nAM<=t,x n:能力値 t:成功値 x:必要成功数
18
- 例)3AM<=2,1: ダイスを3個振って、成功値2,必要成功数1で判定。その結果(成功数,成功・失敗)を表示
17
+ ■ステータスのダイス判定 n[+-b]AM<=t,x n:能力値 b:修正値(省略可能) t:成功値 x:必要成功数
18
+ 例)3AM<=2,1: ダイスを3個振って、成功値2,必要成功数1で判定。その結果(成功数,成功・失敗,クリティカル,ファンブル)を表示
19
19
 
20
- ■探索技能のダイス判定 AI<=t,x t:探索技能レベル x:必要成功数
21
- 例)AI<=3,1: ダイスを3個振って、探索技能レベル3,必要成功数1で判定。その結果(成功数,成功・失敗)を表示
20
+ ■探索技能のダイス判定 [+-b]AI<=t,x t:探索技能レベル b:修正値(省略可能) x:必要成功数
21
+ 例)AI<=3,1: ダイスを3個振って、探索技能レベル3,必要成功数1で判定。その結果(成功数,成功・失敗,クリティカル,ファンブル)を表示
22
22
 
23
- ■攻撃判定 AA<=t t:戦闘技能レベル
23
+ ■攻撃判定 [+-b]AA<=t t:戦闘技能レベル b:修正値(省略可能)
24
24
  例)AA<=3: ダイスを3個振って、戦闘技能レベル3で判定。その結果(成功・失敗,ダメージ,クリティカル,ファンブル)を表示
25
25
 
26
- ■防御判定 AG=t t:攻撃技能レベル
27
- 例)AG=2: ダイスを3個振って、攻撃技能レベル2で判定。その結果(成功・失敗,ダメージ,クリティカル,ファンブル)を表示
26
+ ■防御判定 [+-b]AG=t t:攻撃技能レベル b:修正値(省略可能)
27
+ 例)AG=2: ダイスを3個振って、攻撃技能レベル2で判定。その結果(成功・失敗,ダメージ軽減,クリティカル,ファンブル)を表示
28
28
 
29
- ■回避判定 AD=t t:攻撃技能レベル
29
+ ■回避判定 [+-b]AD=t t:攻撃技能レベル b:修正値(省略可能)
30
30
  例)AD=3: ダイスを1個振って、攻撃技能レベル3で判定。その結果(成功・失敗)を表示
31
31
  INFO_MESSAGETEXT
32
32
 
33
- register_prefix('\d*A[MIAGD]')
33
+ register_prefix('[-+\d]*A[MIAGD]')
34
34
 
35
35
  def initialize(command)
36
36
  super(command)
@@ -48,27 +48,53 @@ module BCDice
48
48
 
49
49
  private
50
50
 
51
+ def with_symbol(number)
52
+ if number == 0
53
+ return ""
54
+ elsif number > 0
55
+ return "+#{number}"
56
+ else
57
+ return number.to_s
58
+ end
59
+ end
60
+
51
61
  # ステータスの判定
52
62
  # @param [String] command
53
63
  # @return [Result]
54
64
  def resolute_action(command)
55
- m = /^(\d+)AM<=(\d+),(\d)$/.match(command)
65
+ m = /^(\d+)([-+]\d+)?AM<=(\d+),(\d)$/.match(command)
56
66
  return nil unless m
57
67
 
58
68
  num_dice = m[1].to_i
59
- num_target = m[2].to_i
60
- num_success = m[3].to_i
69
+ num_bonus = m[2].to_i
70
+ num_target = m[3].to_i
71
+ num_success = m[4].to_i
61
72
 
62
- dice = @randomizer.roll_barabara(num_dice, 6).sort
73
+ dice = @randomizer.roll_barabara(num_dice + num_bonus, 6).sort
63
74
  dice_text = dice.join(",")
64
75
  success_num = dice.count { |val| val <= num_target }
65
- output = "(#{num_dice}AM<=#{num_target},#{num_success}) #{dice_text} 成功数#{success_num}"
66
- if success_num >= num_success
67
- output += " > 成功"
68
- return Result.success(output)
69
- else
70
- output += " > 失敗"
71
- return Result.failure(output)
76
+ is_critical = dice.include?(1) && dice.include?(2) && dice.include?(3)
77
+ is_fumble = dice.include?(4) && dice.include?(5) && dice.include?(6)
78
+
79
+ return Result.new.tap do |result|
80
+ result.critical = is_critical
81
+ result.fumble = is_fumble
82
+ result.condition = (success_num >= num_success)
83
+
84
+ sequence = [
85
+ "(#{num_dice}#{with_symbol(num_bonus)}AM<=#{num_target},#{num_success})",
86
+ dice_text,
87
+ "成功数#{success_num}",
88
+ if result.success?
89
+ "成功"
90
+ else
91
+ "失敗"
92
+ end
93
+ ].compact
94
+ sequence.push("クリティカル") if result.critical?
95
+ sequence.push("ファンブル") if result.fumble?
96
+
97
+ result.text = sequence.join(" > ")
72
98
  end
73
99
  end
74
100
 
@@ -76,22 +102,38 @@ module BCDice
76
102
  # @param [String] command
77
103
  # @return [Result]
78
104
  def resolute_investigation(command)
79
- m = /^AI<=(\d+),(\d)$/.match(command)
105
+ m = /^([-+]\d+)?AI<=(\d+),(\d)$/.match(command)
80
106
  return nil unless m
81
107
 
82
- num_target = m[1].to_i
83
- num_success = m[2].to_i
108
+ num_bonus = m[1].to_i
109
+ num_target = m[2].to_i
110
+ num_success = m[3].to_i
84
111
 
85
- dice = @randomizer.roll_barabara(3, 6).sort
112
+ dice = @randomizer.roll_barabara(3 + num_bonus, 6).sort
86
113
  dice_text = dice.join(",")
87
114
  success_num = dice.count { |val| val <= num_target }
88
- output = "(AI<=#{num_target},#{num_success}) #{dice_text} 成功数#{success_num}"
89
- if success_num >= num_success
90
- output += " > 成功"
91
- return Result.success(output)
92
- else
93
- output += " > 失敗"
94
- return Result.failure(output)
115
+ is_critical = dice.include?(1) && dice.include?(2) && dice.include?(3)
116
+ is_fumble = dice.include?(4) && dice.include?(5) && dice.include?(6)
117
+
118
+ return Result.new.tap do |result|
119
+ result.critical = is_critical
120
+ result.fumble = is_fumble
121
+ result.condition = (success_num >= num_success)
122
+
123
+ sequence = [
124
+ "(#{with_symbol(num_bonus)}AI<=#{num_target},#{num_success})",
125
+ dice_text,
126
+ "成功数#{success_num}",
127
+ if result.success?
128
+ "成功"
129
+ else
130
+ "失敗"
131
+ end
132
+ ].compact
133
+ sequence.push("クリティカル") if result.critical?
134
+ sequence.push("ファンブル") if result.fumble?
135
+
136
+ result.text = sequence.join(" > ")
95
137
  end
96
138
  end
97
139
 
@@ -99,25 +141,25 @@ module BCDice
99
141
  # @param [String] command
100
142
  # @return [Result]
101
143
  def resolute_attacking(command)
102
- m = /^AA<=(\d+)$/.match(command)
144
+ m = /^([-+]\d+)?AA<=(\d+)$/.match(command)
103
145
  return nil unless m
104
146
 
105
- num_target = m[1].to_i
147
+ num_bonus = m[1].to_i
148
+ num_target = m[2].to_i
106
149
 
107
- dice = @randomizer.roll_barabara(3, 6).sort
150
+ dice = @randomizer.roll_barabara(3 + num_bonus, 6).sort
108
151
  dice_text = dice.join(",")
109
152
  success_num = dice.count { |val| val <= num_target }
110
- is_critical = dice[0] == 1 && dice[1] == 2 && dice[2] == 3
111
- is_fumble = dice[0] == 4 && dice[1] == 5 && dice[2] == 6
153
+ is_critical = dice.include?(1) && dice.include?(2) && dice.include?(3)
154
+ is_fumble = dice.include?(4) && dice.include?(5) && dice.include?(6)
155
+
112
156
  damage1 = dice.max
113
157
  damage2 = dice.max
114
- if dice[0] == dice[1] && dice[1] == dice[2] && dice[2] <= num_target
115
- damage2 += 6
116
- damage1 = damage2
117
- elsif dice[0] == dice[1] && dice[1] <= num_target
118
- damage2 += 3
119
- elsif dice[1] == dice[2] && dice[2] <= num_target
120
- damage2 += 3
158
+ (1..num_target).each do |idx|
159
+ if dice.count(idx) > 1
160
+ now_damage = damage1 + 3 * (dice.count(idx) - 1)
161
+ damage2 = now_damage if damage2 < now_damage
162
+ end
121
163
  end
122
164
 
123
165
  return Result.new.tap do |result|
@@ -126,7 +168,7 @@ module BCDice
126
168
  result.condition = (success_num > 0)
127
169
 
128
170
  sequence = [
129
- "(AA<=#{num_target})",
171
+ "(#{with_symbol(num_bonus)}AA<=#{num_target})",
130
172
  dice_text,
131
173
  "成功数#{success_num}",
132
174
  if result.success?
@@ -136,11 +178,7 @@ module BCDice
136
178
  end
137
179
  ].compact
138
180
  if result.success?
139
- if damage1 == damage2
140
- sequence.push("ダメージ(#{damage1})")
141
- else
142
- sequence.push("ダメージ(#{damage1}か#{damage2})")
143
- end
181
+ sequence.push("最大ダメージ(#{damage2})")
144
182
  end
145
183
  sequence.push("クリティカル") if result.critical?
146
184
  sequence.push("ファンブル") if result.fumble?
@@ -153,16 +191,17 @@ module BCDice
153
191
  # @param [String] command
154
192
  # @return [Result]
155
193
  def resolute_guarding(command)
156
- m = /^AG=(\d+)$/.match(command)
194
+ m = /^([-+]\d+)?AG=(\d+)$/.match(command)
157
195
  return nil unless m
158
196
 
159
- num_target = m[1].to_i
197
+ num_bonus = m[1].to_i
198
+ num_target = m[2].to_i
160
199
 
161
- dice = @randomizer.roll_barabara(3, 6).sort
200
+ dice = @randomizer.roll_barabara(3 + num_bonus, 6).sort
162
201
  dice_text = dice.join(",")
163
202
  success_num = dice.count(num_target)
164
- is_critical = dice[0] == 1 && dice[1] == 2 && dice[2] == 3
165
- is_fumble = dice[0] == 4 && dice[1] == 5 && dice[2] == 6
203
+ is_critical = dice.include?(1) && dice.include?(2) && dice.include?(3)
204
+ is_fumble = dice.include?(4) && dice.include?(5) && dice.include?(6)
166
205
 
167
206
  return Result.new.tap do |result|
168
207
  result.critical = is_critical
@@ -170,7 +209,7 @@ module BCDice
170
209
  result.condition = (success_num > 0)
171
210
 
172
211
  sequence = [
173
- "(AG=#{num_target})",
212
+ "(#{with_symbol(num_bonus)}AG=#{num_target})",
174
213
  dice_text,
175
214
  "成功数#{success_num}",
176
215
  if result.success?
@@ -190,12 +229,13 @@ module BCDice
190
229
  # @param [String] command
191
230
  # @return [Result]
192
231
  def resolute_dodging(command)
193
- m = /^AD=(\d+)$/.match(command)
232
+ m = /^([-+]\d+)?AD=(\d+)$/.match(command)
194
233
  return nil unless m
195
234
 
196
- num_target = m[1].to_i
235
+ num_bonus = m[1].to_i
236
+ num_target = m[2].to_i
197
237
 
198
- dice = @randomizer.roll_barabara(1, 6)
238
+ dice = @randomizer.roll_barabara(1 + num_bonus, 6)
199
239
  dice_text = dice.join(",")
200
240
  success_num = dice.count(num_target)
201
241
 
@@ -203,7 +243,7 @@ module BCDice
203
243
  result.condition = (success_num > 0)
204
244
 
205
245
  sequence = [
206
- "(AD=#{num_target})",
246
+ "(#{with_symbol(num_bonus)}AD=#{num_target})",
207
247
  dice_text,
208
248
  "成功数#{success_num}",
209
249
  if result.success?
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class Arianrhod_Korean < Arianrhod
6
+ # ゲームシステムの識別子
7
+ ID = 'Arianrhod:Korean'
8
+
9
+ # ゲームシステム名
10
+ NAME = '아리안로드RPG'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = '国際化:Korean:아리안로드RPG'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
17
+ ・크리티컬, 펌블의 자동판정을 행합니다.(크리티컬 시의 추가 대미지도 표시됩니다)
18
+ ・D66 다이스 있음
19
+ INFO_MESSAGE_TEXT
20
+
21
+ def initialize(command)
22
+ super(command)
23
+
24
+ @locale = :ko_kr
25
+ end
26
+
27
+ register_prefix_from_super_class()
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,244 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bcdice/dice_table/range_table'
4
+
5
+ module BCDice
6
+ module GameSystem
7
+ class BlackJacket < Base
8
+ # ゲームシステムの識別子
9
+ ID = 'BlackJacket'
10
+
11
+ # ゲームシステム名
12
+ NAME = 'ブラックジャケットRPG'
13
+
14
+ # ゲームシステム名の読みがな
15
+ SORT_KEY = 'ふらつくしあけつとRPG'
16
+
17
+ # ダイスボットの使い方
18
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
19
+ ・行為判定(BJx)
20
+  x:成功率
21
+  例)BJ80
22
+  クリティカル、ファンブルの自動的判定を行います。
23
+  「BJ50+20-30」のように加減算記述も可能。
24
+  成功率は上限100%、下限0%
25
+ ・デスチャート(DCxY)
26
+  x:チャートの種類。肉体:DCL、精神:DCS、環境:DCC
27
+  Y=マイナス値
28
+  例)DCL5:ライフが -5 の判定
29
+    DCS3:サニティーが -3 の判定
30
+    DCC0:クレジット 0 の判定
31
+ ・チャレンジ・ペナルティ・チャート(CPC)
32
+ ・サイドトラック・チャート(STC)
33
+ INFO_MESSAGE_TEXT
34
+
35
+ def eval_game_system_specific_command(command)
36
+ resolute_action(command) || roll_death_chart(command) || roll_tables(command, TABLES)
37
+ end
38
+
39
+ private
40
+
41
+ def resolute_action(command)
42
+ m = /^BJ(\d+([+-]\d+)*)$/.match(command)
43
+ unless m
44
+ return nil
45
+ end
46
+
47
+ success_rate = ArithmeticEvaluator.eval(m[1])
48
+
49
+ roll_result, dice10, dice01 = roll_d100
50
+ roll_result_text = format('%02d', roll_result)
51
+
52
+ result = action_result(roll_result, dice10, dice01, success_rate)
53
+
54
+ sequence = [
55
+ "行為判定(成功率:#{success_rate}%)",
56
+ "1D100[#{dice10},#{dice01}]=#{roll_result_text}",
57
+ roll_result_text.to_s,
58
+ result.text
59
+ ]
60
+
61
+ result.text = sequence.join(" > ")
62
+ result
63
+ end
64
+
65
+ SUCCESS_STR = "成功"
66
+ FAILURE_STR = "失敗"
67
+ CRITICAL_STR = (SUCCESS_STR + " > クリティカル! パワーの代償1/2").freeze
68
+ FUMBLE_STR = (FAILURE_STR + " > ファンブル! パワーの代償2倍&振り直し不可").freeze
69
+ MISERY_STR = (FAILURE_STR + " > ミザリー! パワーの代償2倍&振り直し不可").freeze
70
+
71
+ def action_result(total, tens, ones, success_rate)
72
+ if total == 100
73
+ Result.fumble(MISERY_STR)
74
+ elsif success_rate <= 0
75
+ Result.fumble(FUMBLE_STR)
76
+ elsif total <= success_rate - 100
77
+ Result.critical(CRITICAL_STR)
78
+ elsif tens == ones
79
+ if total <= success_rate
80
+ Result.critical(CRITICAL_STR)
81
+ else
82
+ Result.fumble(FUMBLE_STR)
83
+ end
84
+ elsif total <= success_rate
85
+ Result.success(SUCCESS_STR)
86
+ else
87
+ Result.failure(FAILURE_STR)
88
+ end
89
+ end
90
+
91
+ def roll_d100
92
+ dice10 = @randomizer.roll_once(10)
93
+ dice10 = 0 if dice10 == 10
94
+ dice01 = @randomizer.roll_once(10)
95
+ dice01 = 0 if dice01 == 10
96
+
97
+ roll_result = dice10 * 10 + dice01
98
+ roll_result = 100 if roll_result == 0
99
+
100
+ return roll_result, dice10, dice01
101
+ end
102
+
103
+ class DeathChart
104
+ def initialize(name, chart)
105
+ @name = name
106
+ @chart = chart.freeze
107
+
108
+ if @chart.size != 11
109
+ raise ArgumentError, "unexpected chart size #{name.inspect} (given #{@chart.size}, expected 11)"
110
+ end
111
+ end
112
+
113
+ # @param randomizer [Randomizer]
114
+ # @param minus_score [Integer]
115
+ # @return [String]
116
+ def roll(randomizer, minus_score)
117
+ dice = randomizer.roll_once(10)
118
+ key_number = dice + minus_score
119
+
120
+ key_text, chosen = at(key_number)
121
+
122
+ return "デスチャート(#{@name})[マイナス値:#{minus_score} + 1D10(->#{dice}) = #{key_number}] > #{key_text} : #{chosen}"
123
+ end
124
+
125
+ private
126
+
127
+ # key_numberの10から20がindexの0から10に対応する
128
+ def at(key_number)
129
+ if key_number < 10
130
+ ["10以下", @chart.first]
131
+ elsif key_number > 20
132
+ ["20以上", @chart.last]
133
+ else
134
+ [key_number.to_s, @chart[key_number - 10]]
135
+ end
136
+ end
137
+ end
138
+
139
+ def roll_death_chart(command)
140
+ m = /^DC([LSC])(\d+)$/i.match(command)
141
+ unless m
142
+ return m
143
+ end
144
+
145
+ chart = DEATH_CHARTS[m[1]]
146
+ minus_score = m[2].to_i
147
+
148
+ return chart.roll(@randomizer, minus_score)
149
+ end
150
+
151
+ DEATH_CHARTS = {
152
+ 'L' => DeathChart.new(
153
+ '肉体',
154
+ [
155
+ "何も無し。キミは奇跡的に一命を取り留めた。闘いは続く。",
156
+ "激痛が走る。以後、イベント終了時まで、全ての判定の成功率-10%。",
157
+ "もう、体が動かない……。キミは[硬直2]を受ける。",
158
+ "渾身の一撃!! キミは〈生存〉判定を行なう。失敗した場合、[死亡]する。",
159
+ "突然、目の前が真っ暗になった。キミは[気絶2]を受ける。",
160
+ "以後、イベント終了時まで、全ての判定の成功率-20%。",
161
+ "記録的一撃!! キミは〈生存〉-20%の判定を行なう。失敗した場合、[死亡]する。",
162
+ "生きているのか死んでいるのか。キミは[瀕死2]を受ける。",
163
+ "叙事詩的一撃!! キミは〈生存〉-30%の判定を行なう。失敗した場合、[死亡]する。",
164
+ "以後、イベント終了時まで、全ての判定の成功率-30%。",
165
+ "神話的一撃!! キミは宙を舞って三回転ほどした後、地面に叩きつけられる。見るも無惨な姿。肉体は原型を留めていない(キミは[死亡]した)。",
166
+ ]
167
+ ),
168
+ 'S' => DeathChart.new(
169
+ '精神',
170
+ [
171
+ "何も無し。キミは歯を食いしばってストレスに耐えた。",
172
+ "以後、イベント終了時まで、全ての判定の成功率-10%。",
173
+ "云い知れぬ恐怖がキミを襲う。キミは[恐怖2]を受ける。",
174
+ "とても傷ついた。キミは〈意思〉判定を行なう。失敗した場合、[絶望]してNPCとなる。",
175
+ "キミは意識を失った。キミは[気絶2]を受ける。",
176
+ "以後、イベント終了時まで、全ての判定の成功率-20%。",
177
+ "信じる者にだまされたような痛み。キミは〈意思〉-20%の判定を行なう。失敗した場合、[絶望]してNPCとなる。",
178
+ "仲間に裏切られたのかも知れない。キミは[混乱2]を受ける。",
179
+ "あまりに残酷な現実。キミは〈意思〉-30%の判定を行なう。失敗した場合、[絶望]してNPCとなる。",
180
+ "以後、イベント終了時まで、全ての判定の成功率-30%。",
181
+ "宇宙開闢の理に触れるも、それは人類の認識限界を超える何かであった。キミは[絶望]し、以後NPCとなる。",
182
+ ]
183
+ ),
184
+ 'C' => DeathChart.new(
185
+ '環境',
186
+ [
187
+ "何も無し。キミは黒い噂を握りつぶした。",
188
+ "以後、イベント終了時まで、全ての判定の成功率-10%。",
189
+ "ピンチ! 以後、ラウンド終了時まで、キミはカルマを使用できない。",
190
+ "悪い噂が流れる。キミは〈交渉〉判定を行なう。失敗した場合、キミは仲間からの信頼を失って[無縁]され、NPCとなる。",
191
+ "以後、イベント終了時まで、代償にクレジットを消費するパワーを使用できない。",
192
+ "キミの悪評が世間に知れ渡る。協力者からの支援が打ち切られる。以後、シナリオ終了時まで、全ての判定の成功率-20%。",
193
+ "裏切り!! キミは〈経済〉-20%の判定を行なう。失敗した場合、キミは周囲からの信頼を失い、[無縁]され、NPCとなる。",
194
+ "以後、シナリオ終了時まで、【環境】系の技能のレベルがすべて0となる。",
195
+ "捏造報道? 身に覚えのない背信行為がスクープとして報道される。キミは〈心理〉-30%の判定を行なう。失敗した場合、キミは人としての尊厳を失い、[無縁]を受ける。",
196
+ "以後、イベント終了時まで、全ての判定の成功率-30%。",
197
+ "キミの名は史上最悪の汚点として歴史に刻まれる。もはらキミを信じる仲間はなく、キミを助ける社会もない。キミは[無縁]され、以後NPCとなる。",
198
+ ]
199
+ )
200
+ }.freeze
201
+
202
+ TABLES = {
203
+ "CPC" => DiceTable::Table.new(
204
+ "チャレンジ・ペナルティ・チャート",
205
+ "1D10",
206
+ [
207
+ "逝去\n助けるべきNPC(ヒロインなど)が死亡する。",
208
+ "黒星\n敵が目的を成就し、事件はPCの敗北で終了する。そのまま余韻フェイズへ。",
209
+ "活性\n敵のボスのライフを2倍にしたうえで決戦フェイズを開始する。",
210
+ "攻勢\n敵ボスの与ダメージに+2D6の修正を与えたうえで決戦フェイズを開始する。",
211
+ "大挙\n敵の数(ボス以外)を2倍にしたうえで決戦フェイズを開始する。",
212
+ "暗黒\nすべてのエリアを[暗闇]にしたうえで決戦フェイズを開始する。",
213
+ "猛火\n2つの戦場エリアを[ダメージゾーン2]にして、決戦フェイズを開始する。",
214
+ "伏兵\n敵の半分をエリア1とエリア2に移動させた状態で決戦フェイズを開始する。",
215
+ "満腹\nボス以外の敵のライフをすべて2倍にしたうえで決戦フェイズを開始する。",
216
+ "封印\n決戦フェイズの間、PCはカルマを使用できない。決戦フェイズを開始する。"
217
+ ]
218
+ ),
219
+ "STC" => DiceTable::Table.new(
220
+ "サイドトラック・チャート",
221
+ "1D10",
222
+ [
223
+ "邂逅\n偶然、NPCと出会う。どのNPCが現れるかはGMが決定すること。",
224
+ "事故\n交通事故に出くわす。周囲ではパニックが起きているかも知れない。",
225
+ "午睡\n強烈な睡魔に襲われる。まさか、新手のヴィランの能力か?",
226
+ "告白\nNPCのひとりから、今まで秘めていた思いを吐露される。",
227
+ "設定\n新たな設定が明かされる。実はNPCの父だったとか、生来目が見えん、とか。",
228
+ "刺客\n何者かから攻撃を受ける。第3勢力か?",
229
+ "会敵\n偶然、仇敵のひとりと出くわす。追うべきか? 無視すべきか?",
230
+ "不審\n怪しい人物を見かける。追うべきか? 無視すべきか?",
231
+ "遭遇\nシナリオと関係のないヴィラン組織と遭遇する。",
232
+ "平和\n特に何も起きなかった。",
233
+ ]
234
+ ),
235
+ }.freeze
236
+
237
+ register_prefix(
238
+ 'BJ',
239
+ 'DC[LSC]',
240
+ TABLES.keys
241
+ )
242
+ end
243
+ end
244
+ end
@@ -19,7 +19,7 @@ module BCDice
19
19
 
20
20
  # ダイスボットの使い方
21
21
  HELP_MESSAGE = <<~MESSAGETEXT
22
- xCD@z>=y: x個の10面ダイスで目標値y、クリティカルラインzの判定を行う
22
+ xCD@z>=y: x個の10面ダイスで目標値y(省略時5)、クリティカルラインz(省略時10)の判定を行う。
23
23
  SLT: 技能レベル表を振る
24
24
  DCT: 遅延イベント表を振る
25
25
  MESSAGETEXT
@@ -87,7 +87,7 @@ module BCDice
87
87
  parser = Command::Parser.new('CD', round_type: round_type)
88
88
  .has_prefix_number
89
89
  .enable_critical
90
- .restrict_cmp_op_to(:>=)
90
+ .restrict_cmp_op_to(:>=, nil)
91
91
  cmd = parser.parse(command)
92
92
 
93
93
  unless cmd
@@ -95,8 +95,9 @@ module BCDice
95
95
  end
96
96
 
97
97
  dice_list = @randomizer.roll_barabara(cmd.prefix_number, 10)
98
- critical = cmd.critical&.clamp(cmd.target_number, 10) || 10
99
- succeed_num = dice_list.count { |x| x >= cmd.target_number }
98
+ target_num = cmd.target_number || 5
99
+ critical = cmd.critical&.clamp(target_num, 10) || 10
100
+ succeed_num = dice_list.count { |x| x >= target_num }
100
101
  critical_num = dice_list.count { |x| x >= critical }
101
102
 
102
103
  text = [
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bcdice/game_system/Cthulhu"
4
+
5
+ module BCDice
6
+ module GameSystem
7
+ class Cthulhu_English < Cthulhu
8
+ # ゲームシステムの識別子
9
+ ID = 'Cthulhu:English'
10
+
11
+ # ゲームシステム名
12
+ NAME = 'Call of Cthulhu'
13
+
14
+ # ゲームシステム名の読みがな
15
+ SORT_KEY = '国際化:English:Call of Cthulhu'
16
+
17
+ # ダイスボットの使い方
18
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
19
+ c=Critical Rate / f=Fumble Rate / s=Special
20
+
21
+ 1d100<=n c・f・s AllOff(Does Simple Numeric Comparison Only)
22
+
23
+ ・Roll Command that determines cfs
24
+
25
+ CC Does a 1d100 roll c=1、f=100
26
+ CCB Same as above、c=5、f=96
27
+
28
+ Ex:CC<=80 (Rolls using 80 as skill value with 1% cf rule applied)
29
+ Ex:CCB<=55 (Rolls using 55 as skill value with 5% cf rule applied)
30
+
31
+ ・About Roll Combination
32
+
33
+ CBR(x,y) c=1、f=100
34
+ CBRB(x,y) c=5、f=96
35
+
36
+ ・About Opposed Rolls
37
+ RES(x-y) c=1、f=100
38
+ RESB(x-y) c=5、f=96
39
+
40
+ ※Malfunction Number Determination
41
+
42
+ ・CC(x) c=1、f=100
43
+ x=Malfunction Number. Outputs(text "Fumble&Malfunction")together, when roll result is equal or above x, and fumble happens simultaneously.
44
+ If not a fumble, outputs text "Malfunction" regardless of success/failure(Outputs the overwritten result, not outputting success/failure)
45
+
46
+ ・CCB(x) c=5、f=96
47
+ Same as above
48
+ INFO_MESSAGE_TEXT
49
+
50
+ register_prefix_from_super_class()
51
+
52
+ def initialize(command)
53
+ super(command)
54
+
55
+ @locale = :en_us
56
+ end
57
+ end
58
+ end
59
+ end
@@ -44,8 +44,18 @@ module BCDice
44
44
   STOREA :店主またはレジ係
45
45
   STOREB :変わった客その1
46
46
   STOREC :変わった客その2
47
+ ・夜の市
48
+  NMCT :商品の分野
49
+  NMCFO :食品とドラッグ
50
+  NMCME :個人用電子機器
51
+  NMCWE :武器と防具
52
+  NMCCY :サイバーウェア
53
+  NMCFA :衣料品とファッションウェア
54
+  NMCSU :サバイバル用品
47
55
  HELP
48
56
 
57
+ TABLES = translate_tables(@locale)
58
+
49
59
  # 判定の正規表現
50
60
  CP_RE = /^CP(?<ability>\d+)?(?<modifier>[+-]\d+)?(?<target>>=\d+)?/.freeze
51
61
 
@@ -105,21 +115,21 @@ module BCDice
105
115
  result.text += ' > '
106
116
 
107
117
  if result.critical?
108
- result.text += '決定的成功!'
118
+ result.text += "#{translate('CyberpunkRed.critical')}"
109
119
  result.text += "#{dices.last}[#{dices.last}] > "
110
120
  end
111
121
  if result.fumble?
112
- result.text += '決定的失敗!'
122
+ result.text += "#{translate('CyberpunkRed.fumble')}"
113
123
  result.text += "#{dices.last}[#{dices.last}] > "
114
124
  end
115
125
 
116
126
  result.text += total.to_s
117
127
 
118
128
  if result.success?
119
- result.text += '成功'
129
+ result.text += "#{translate('success')}"
120
130
  end
121
131
  if result.failure?
122
- result.text += '失敗'
132
+ result.text += "#{translate('failure')}"
123
133
  end
124
134
 
125
135
  return result