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
@@ -14,23 +14,23 @@ module BCDice
|
|
14
14
|
|
15
15
|
# ダイスボットの使い方
|
16
16
|
HELP_MESSAGE = <<~INFO_MESSAGETEXT
|
17
|
-
■ステータスのダイス判定
|
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
|
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('
|
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
|
-
|
60
|
-
|
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
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
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
|
-
|
83
|
-
|
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
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
-
|
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
|
111
|
-
is_fumble = dice
|
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
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
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
|
-
|
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
|
-
|
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
|
165
|
-
is_fumble = dice
|
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
|
-
|
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
|
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
|
-
|
99
|
-
|
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
|