bcdice 3.6.0 → 3.8.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 +56 -0
- data/i18n/Arianrhod/ja_jp.yml +3 -0
- data/i18n/Emoklore/ja_jp.yml +7 -0
- data/i18n/FutariSousa/ja_jp.yml +431 -0
- data/i18n/LogHorizon/ja_jp.yml +1 -1
- data/i18n/SwordWorld/ja_jp.yml +1 -0
- data/i18n/SwordWorld/zh_hans.yml +7 -0
- data/i18n/SwordWorld2_0/zh_hans.yml +37 -0
- data/i18n/SwordWorld2_5/ja_jp.yml +1 -1
- data/i18n/SwordWorld2_5/zh_hans.yml +57 -0
- data/lib/bcdice/arithmetic/parser.rb +1 -1
- data/lib/bcdice/command/parser.rb +1 -1
- data/lib/bcdice/common_command/add_dice/parser.rb +106 -74
- data/lib/bcdice/common_command/add_dice.rb +1 -1
- data/lib/bcdice/common_command/barabara_dice/parser.rb +1 -1
- data/lib/bcdice/common_command/calc/parser.rb +1 -1
- data/lib/bcdice/common_command/d66_dice.rb +1 -1
- data/lib/bcdice/common_command/reroll_dice/parser.rb +1 -1
- data/lib/bcdice/common_command/tally_dice/parser.rb +1 -1
- data/lib/bcdice/common_command/upper_dice/parser.rb +1 -1
- data/lib/bcdice/game_system/AngelGear.rb +1 -1
- data/lib/bcdice/game_system/AnimaAnimus.rb +1 -1
- data/lib/bcdice/game_system/Arianrhod.rb +4 -4
- data/lib/bcdice/game_system/AssaultEngine.rb +3 -3
- data/lib/bcdice/game_system/Ayabito.rb +170 -4
- data/lib/bcdice/game_system/BeastBindTrinity.rb +1 -1
- data/lib/bcdice/game_system/BeginningIdol.rb +4 -2
- data/lib/bcdice/game_system/BeginningIdol2022.rb +184 -0
- data/lib/bcdice/game_system/BladeOfArcana.rb +3 -3
- data/lib/bcdice/game_system/Bloodorium.rb +68 -0
- data/lib/bcdice/game_system/ConvictorDrive.rb +117 -0
- data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional.rb +1 -1
- data/lib/bcdice/game_system/Cthulhu7th_Korean.rb +1 -1
- data/lib/bcdice/game_system/CyberpunkRed.rb +2 -6
- data/lib/bcdice/game_system/DeadlineHeroes.rb +1 -1
- data/lib/bcdice/game_system/DungeonsAndDragons5.rb +196 -0
- data/lib/bcdice/game_system/EmbryoMachine.rb +4 -4
- data/lib/bcdice/game_system/Emoklore.rb +8 -8
- data/lib/bcdice/game_system/FutariSousa.rb +31 -5
- data/lib/bcdice/game_system/GURPS.rb +1 -1
- data/lib/bcdice/game_system/GehennaAn.rb +2 -2
- data/lib/bcdice/game_system/GhostLive.rb +144 -0
- data/lib/bcdice/game_system/GoblinSlayer.rb +30 -8
- data/lib/bcdice/game_system/HunterTheReckoning5th.rb +152 -0
- data/lib/bcdice/game_system/IfIfIf.rb +648 -0
- data/lib/bcdice/game_system/Kutulu.rb +95 -0
- data/lib/bcdice/game_system/LostRoyal.rb +1 -1
- data/lib/bcdice/game_system/NobunagasBlackCastle.rb +237 -0
- data/lib/bcdice/game_system/OracleEngine.rb +1 -1
- data/lib/bcdice/game_system/Raisondetre.rb +1 -1
- data/lib/bcdice/game_system/RokumonSekai2.rb +1 -1
- data/lib/bcdice/game_system/SajinsenkiAGuS.rb +154 -0
- data/lib/bcdice/game_system/Sengensyou.rb +59 -0
- data/lib/bcdice/game_system/ShinkuuGakuen.rb +1 -1
- data/lib/bcdice/game_system/ShinobiGami.rb +14 -1
- data/lib/bcdice/game_system/SkynautsBouken.rb +93 -2
- data/lib/bcdice/game_system/StellarLife.rb +1 -1
- data/lib/bcdice/game_system/StrangerOfSwordCity.rb +1 -1
- data/lib/bcdice/game_system/SwordWorld.rb +2 -2
- data/lib/bcdice/game_system/SwordWorld2_0_SimplifiedChinese.rb +84 -0
- data/lib/bcdice/game_system/SwordWorld2_5_SimplifiedChinese.rb +95 -0
- data/lib/bcdice/game_system/SwordWorld_SimplifiedChinese.rb +29 -0
- data/lib/bcdice/game_system/TherapieSein.rb +2 -2
- data/lib/bcdice/game_system/Torg.rb +1 -1
- data/lib/bcdice/game_system/TorgEternity.rb +54 -18
- data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +26 -12
- data/lib/bcdice/game_system/VisionConnect.rb +135 -0
- data/lib/bcdice/game_system/Warhammer4.rb +4 -0
- data/lib/bcdice/game_system/WorldOfDarkness.rb +54 -50
- data/lib/bcdice/game_system/cthulhu7th/full_auto.rb +1 -1
- data/lib/bcdice/game_system/filled_with/tresure_tables.rb +1 -1
- data/lib/bcdice/game_system/satasupe/tables.rb +1 -1
- data/lib/bcdice/game_system/sword_world/rating_parser.rb +1 -1
- data/lib/bcdice/game_system.rb +15 -0
- data/lib/bcdice/version.rb +1 -1
- metadata +26 -6
|
@@ -67,7 +67,7 @@ module BCDice
|
|
|
67
67
|
def cp_roll_result(command)
|
|
68
68
|
parser = Command::Parser.new('CP', round_type: RoundType::FLOOR)
|
|
69
69
|
.enable_suffix_number
|
|
70
|
-
.restrict_cmp_op_to(nil,
|
|
70
|
+
.restrict_cmp_op_to(nil, :>)
|
|
71
71
|
parsed = parser.parse(command)
|
|
72
72
|
return nil if parsed.nil?
|
|
73
73
|
|
|
@@ -96,11 +96,7 @@ module BCDice
|
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
if parsed.target_number
|
|
99
|
-
|
|
100
|
-
result.success = true
|
|
101
|
-
else
|
|
102
|
-
result.failure = true
|
|
103
|
-
end
|
|
99
|
+
result.condition = total > parsed.target_number
|
|
104
100
|
end
|
|
105
101
|
|
|
106
102
|
result.text = "(#{dice_cnt}D#{dice_face}#{Format.modifier(modify_number)}#{parsed.cmp_op}#{parsed.target_number})"
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BCDice
|
|
4
|
+
module GameSystem
|
|
5
|
+
class DungeonsAndDragons5 < Base
|
|
6
|
+
# ゲームシステムの識別子
|
|
7
|
+
ID = 'DungeonsAndDragons5'
|
|
8
|
+
|
|
9
|
+
# ゲームシステム名
|
|
10
|
+
NAME = 'ダンジョンズ&ドラゴンズ第5版'
|
|
11
|
+
|
|
12
|
+
# ゲームシステム名の読みがな
|
|
13
|
+
SORT_KEY = 'たんしよんすあんととらこんす5'
|
|
14
|
+
|
|
15
|
+
# ダイスボットの使い方
|
|
16
|
+
HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
|
|
17
|
+
・攻撃ロール AT[x][>=t][y]
|
|
18
|
+
x:+-修正。省略可。
|
|
19
|
+
y:有利(A), 不利(D)。省略可。
|
|
20
|
+
t:敵のアーマークラス。>=を含めて省略可。
|
|
21
|
+
ファンブル/失敗/成功/クリティカル を自動判定。
|
|
22
|
+
例)AT AT>=10 AT+5>=18 AT-3>=16 ATA AT>=10A AT+3>=18A AT-3>=16 ATD AT>=10D AT+5>=18D AT-5>=16D
|
|
23
|
+
|
|
24
|
+
・能力値判定 AR[x][>=t][y]
|
|
25
|
+
攻撃ロールと同様。失敗/成功を自動判定。
|
|
26
|
+
例)AR AR>=10 AR+5>=18 AR-3>=16 ARA AR>=10A AR+3>=18A AR-3>=16 ARD AR>=10D AR+5>=18D AR-5>=16D
|
|
27
|
+
|
|
28
|
+
INFO_MESSAGE_TEXT
|
|
29
|
+
|
|
30
|
+
register_prefix('AT([+-]\d+)?(>=\d+)?[AD]?', 'AR([+-]\d+)?(>=\d+)?[AD]?')
|
|
31
|
+
|
|
32
|
+
def initialize(command)
|
|
33
|
+
super(command)
|
|
34
|
+
|
|
35
|
+
@sort_barabara_dice = false # バラバラロール(Bコマンド)でソート無
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def eval_game_system_specific_command(command)
|
|
39
|
+
attack_roll(command) || ability_roll(command)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def number_with_sign_from_int(number)
|
|
43
|
+
if number == 0
|
|
44
|
+
return ""
|
|
45
|
+
elsif number > 0
|
|
46
|
+
return "+#{number}"
|
|
47
|
+
else
|
|
48
|
+
return number.to_s
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def attack_roll(command)
|
|
53
|
+
m = /^AT([-+]\d+)?(>=(\d+))?([AD]?)/.match(command)
|
|
54
|
+
unless m
|
|
55
|
+
return nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
modify = m[1].to_i
|
|
59
|
+
difficulty = m[3].to_i
|
|
60
|
+
advantage = m[4]
|
|
61
|
+
|
|
62
|
+
usedie = 0
|
|
63
|
+
roll_die = ""
|
|
64
|
+
|
|
65
|
+
dice_command = "AT#{number_with_sign_from_int(modify)}"
|
|
66
|
+
if difficulty > 0
|
|
67
|
+
dice_command += ">=#{difficulty}"
|
|
68
|
+
end
|
|
69
|
+
unless advantage.empty?
|
|
70
|
+
dice_command += advantage.to_s
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
output = ["(#{dice_command})"]
|
|
74
|
+
|
|
75
|
+
if advantage.empty?
|
|
76
|
+
usedie = @randomizer.roll_once(20)
|
|
77
|
+
roll_die = usedie
|
|
78
|
+
else
|
|
79
|
+
dice = @randomizer.roll_barabara(2, 20)
|
|
80
|
+
roll_die = "[" + dice.join(",") + "]"
|
|
81
|
+
if advantage == "A"
|
|
82
|
+
usedie = dice.max
|
|
83
|
+
else
|
|
84
|
+
usedie = dice.min
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
if modify != 0
|
|
89
|
+
output.push("#{roll_die}#{number_with_sign_from_int(modify)}")
|
|
90
|
+
output.push((usedie + modify).to_s)
|
|
91
|
+
else
|
|
92
|
+
unless advantage.empty?
|
|
93
|
+
output.push(roll_die)
|
|
94
|
+
end
|
|
95
|
+
output.push(usedie.to_s)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
result = Result.new
|
|
99
|
+
if usedie == 20
|
|
100
|
+
result.critical = true
|
|
101
|
+
result.success = true
|
|
102
|
+
output.push("クリティカル")
|
|
103
|
+
elsif usedie == 1
|
|
104
|
+
result.fumble = true
|
|
105
|
+
output.push("ファンブル")
|
|
106
|
+
elsif difficulty > 0
|
|
107
|
+
if usedie + modify >= difficulty
|
|
108
|
+
result.success = true
|
|
109
|
+
output.push("成功")
|
|
110
|
+
else
|
|
111
|
+
output.push("失敗")
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
Result.new.tap do |r|
|
|
116
|
+
r.text = output.join(" > ")
|
|
117
|
+
if result
|
|
118
|
+
if difficulty > 0 || result.critical? || result.fumble?
|
|
119
|
+
r.condition = result.success?
|
|
120
|
+
end
|
|
121
|
+
r.critical = result.critical?
|
|
122
|
+
r.fumble = result.fumble?
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def ability_roll(command)
|
|
128
|
+
m = /^AR([-+]\d+)?(>=(\d+))?([AD]?)/.match(command)
|
|
129
|
+
unless m
|
|
130
|
+
return nil
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
modify = m[1].to_i
|
|
134
|
+
difficulty = m[3].to_i
|
|
135
|
+
advantage = m[4]
|
|
136
|
+
|
|
137
|
+
usedie = 0
|
|
138
|
+
roll_die = ""
|
|
139
|
+
|
|
140
|
+
dice_command = "AR#{number_with_sign_from_int(modify)}"
|
|
141
|
+
if difficulty > 0
|
|
142
|
+
dice_command += ">=#{difficulty}"
|
|
143
|
+
end
|
|
144
|
+
unless advantage.empty?
|
|
145
|
+
dice_command += advantage.to_s
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
output = ["(#{dice_command})"]
|
|
149
|
+
|
|
150
|
+
if advantage.empty?
|
|
151
|
+
usedie = @randomizer.roll_once(20)
|
|
152
|
+
roll_die = usedie
|
|
153
|
+
else
|
|
154
|
+
dice = @randomizer.roll_barabara(2, 20)
|
|
155
|
+
roll_die = "[" + dice.join(",") + "]"
|
|
156
|
+
if advantage == "A"
|
|
157
|
+
usedie = dice.max
|
|
158
|
+
else
|
|
159
|
+
usedie = dice.min
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
if modify != 0
|
|
164
|
+
output.push("#{roll_die}#{number_with_sign_from_int(modify)}")
|
|
165
|
+
output.push((usedie + modify).to_s)
|
|
166
|
+
else
|
|
167
|
+
unless advantage.empty?
|
|
168
|
+
output.push(roll_die)
|
|
169
|
+
end
|
|
170
|
+
output.push(usedie.to_s)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
result = Result.new
|
|
174
|
+
if difficulty > 0
|
|
175
|
+
if usedie + modify >= difficulty
|
|
176
|
+
result.success = true
|
|
177
|
+
output.push("成功")
|
|
178
|
+
else
|
|
179
|
+
output.push("失敗")
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
Result.new.tap do |r|
|
|
184
|
+
r.text = output.join(" > ")
|
|
185
|
+
if result
|
|
186
|
+
if difficulty > 0
|
|
187
|
+
r.condition = result.success?
|
|
188
|
+
end
|
|
189
|
+
r.critical = result.critical?
|
|
190
|
+
r.fumble = result.fumble?
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
@@ -34,10 +34,10 @@ module BCDice
|
|
|
34
34
|
|
|
35
35
|
def replace_text(string)
|
|
36
36
|
string
|
|
37
|
-
.gsub(/EM(\d+)([
|
|
38
|
-
.gsub(/EM(\d+)([
|
|
39
|
-
.gsub(/EM(\d+)([
|
|
40
|
-
.gsub(/EM(\d+)([
|
|
37
|
+
.gsub(/EM(\d+)([+-][+\-\d]+)(@(\d+))(\#(\d+))/i) { "2R10#{Regexp.last_match(2)}>=#{Regexp.last_match(1)}[#{Regexp.last_match(4)},#{Regexp.last_match(6)}]" }
|
|
38
|
+
.gsub(/EM(\d+)([+-][+\-\d]+)(\#(\d+))/i) { "2R10#{Regexp.last_match(2)}>=#{Regexp.last_match(1)}[20,#{Regexp.last_match(4)}]" }
|
|
39
|
+
.gsub(/EM(\d+)([+-][+\-\d]+)(@(\d+))/i) { "2R10#{Regexp.last_match(2)}>=#{Regexp.last_match(1)}[#{Regexp.last_match(4)},2]" }
|
|
40
|
+
.gsub(/EM(\d+)([+-][+\-\d]+)/i) { "2R10#{Regexp.last_match(2)}>=#{Regexp.last_match(1)}[20,2]" }
|
|
41
41
|
.gsub(/EM(\d+)(@(\d+))(\#(\d+))/i) { "2R10>=#{Regexp.last_match(1)}[#{Regexp.last_match(3)},#{Regexp.last_match(5)}]" }
|
|
42
42
|
.gsub(/EM(\d+)(\#(\d+))/i) { "2R10>=#{Regexp.last_match(1)}[20,#{Regexp.last_match(3)}]" }
|
|
43
43
|
.gsub(/EM(\d+)(@(\d+))/i) { "2R10>=#{Regexp.last_match(1)}[#{Regexp.last_match(3)},2]" }
|
|
@@ -67,7 +67,7 @@ module BCDice
|
|
|
67
67
|
success_value = 2 * critical + success - fumble
|
|
68
68
|
result = compare_result(success_value)
|
|
69
69
|
|
|
70
|
-
result.text = "#{values} > #{success_value} >
|
|
70
|
+
result.text = "#{values} > #{success_value} > #{translate('Emoklore.success_count', count: success_value)} #{result.text}"
|
|
71
71
|
return result
|
|
72
72
|
end
|
|
73
73
|
|
|
@@ -75,19 +75,19 @@ module BCDice
|
|
|
75
75
|
# @return [Result]
|
|
76
76
|
def compare_result(success)
|
|
77
77
|
if success < 0
|
|
78
|
-
Result.fumble("
|
|
78
|
+
Result.fumble(translate("fumble"))
|
|
79
79
|
elsif success == 0
|
|
80
|
-
Result.failure("
|
|
80
|
+
Result.failure(translate("failure"))
|
|
81
81
|
elsif success == 1
|
|
82
|
-
Result.success("
|
|
82
|
+
Result.success(translate("success"))
|
|
83
83
|
elsif success == 2
|
|
84
|
-
Result.critical("
|
|
84
|
+
Result.critical(translate("Emoklore.double"))
|
|
85
85
|
elsif success == 3
|
|
86
|
-
Result.critical("
|
|
86
|
+
Result.critical(translate("Emoklore.triple"))
|
|
87
87
|
elsif success <= 9
|
|
88
|
-
Result.critical("
|
|
88
|
+
Result.critical(translate("Emoklore.miracle"))
|
|
89
89
|
else
|
|
90
|
-
Result.critical("
|
|
90
|
+
Result.critical(translate("Emoklore.catastrophe"))
|
|
91
91
|
end
|
|
92
92
|
end
|
|
93
93
|
|
|
@@ -18,11 +18,11 @@ module BCDice
|
|
|
18
18
|
探偵用:【DT】…10面ダイスを2つ振って判定します。『有利』なら【3DT】、『不利』なら【1DT】を使います。
|
|
19
19
|
助手用:【AS】…6面ダイスを2つ振って判定します。『有利』なら【3AS】、『不利』なら【1AS】を使います。
|
|
20
20
|
・各種表
|
|
21
|
-
|
|
21
|
+
【セッション時】
|
|
22
22
|
異常な癖決定表 SHRD/新・異常な癖決定表 SHND
|
|
23
23
|
普通の?・異常な癖決定表 SHAD/ケイジ異常な癖決定表 SHKD
|
|
24
24
|
口から出る表 SHFM/強引な捜査表 SHBT/すっとぼけ表 SHPI
|
|
25
|
-
事件に夢中表 SHEG/パートナーと……表
|
|
25
|
+
事件に夢中表 SHEG/パートナーと……表 SHWP/何かしている表 SHDS
|
|
26
26
|
奇想天外表 SHFT/急なひらめき表 SHIN/喜怒哀楽表 SHEM
|
|
27
27
|
人間エミュレート表 SHHE/人間エミュレート失敗表 SHHF/パートナーへのいたずら表 SHMP
|
|
28
28
|
思わせぶり表 SHSB/もどかしい表 SHFR/突然どうした表 SHIS
|
|
@@ -38,15 +38,24 @@ module BCDice
|
|
|
38
38
|
思わぬヒント EVH/実験をしてみよう EVX/ゲスト捜査 EVG
|
|
39
39
|
ケイジ聞き込み捜査 EVQ/ケイジ大規模捜査 EVM/こっそり情報の受け渡し EVP
|
|
40
40
|
同僚たちと一緒に捜査する EVO/頻染みの店シチュエーション EVF/ハードBデカアクション EVB
|
|
41
|
+
探偵を大人しくさせる捜査 EVL/伝統的捜査 EVZ/原始的捜査 EVR
|
|
42
|
+
感情表
|
|
43
|
+
感情表A/B FLT66・FLT10
|
|
44
|
+
気に入っているところ FLTL66 /気に入らないところ FLTD66
|
|
45
|
+
ランダム感情決定表(あなた) FLTRA
|
|
46
|
+
顔のパーツ FLTF66/体のパーツ FLTB66/生活習慣 FLTH66
|
|
47
|
+
ふわっとした感覚 FLTS66/他人への態度 FLTA66/ヘビーウェイト FLTW66
|
|
48
|
+
同僚 FLTC66/部下 FLTU66/上司 FLTO66
|
|
49
|
+
捜査のやり方 FLTI66
|
|
41
50
|
調査の障害表 OBT 変調表 ACT 目撃者表 EWT 迷宮入り表 WMT
|
|
51
|
+
思い出の品決定表 MIT エピソード付き思い出の品表 MITE 呼び名表A・B NCT66・NCT10
|
|
42
52
|
【設定時】
|
|
43
53
|
背景表
|
|
44
54
|
探偵 運命の血統 BGDD/天性の才能 BGDG/マニア BGDM
|
|
45
55
|
助手 正義の人 BGAJ/情熱の人 BGAP/巻き込まれの人 BGAI
|
|
46
|
-
身長表 HT たまり場表 BT 関係表 GRT
|
|
56
|
+
身長表 HT たまり場表 BT 関係表 GRT
|
|
47
57
|
職業表A・B JBT66・JBT10 ファッション特徴表A・B FST66・FST10
|
|
48
|
-
|
|
49
|
-
呼び名表A・B NCT66・NCT10
|
|
58
|
+
好きなもの/嫌いなもの表A・B LDT66・LDT10
|
|
50
59
|
MESSAGETEXT
|
|
51
60
|
|
|
52
61
|
def initialize(command)
|
|
@@ -169,6 +178,9 @@ module BCDice
|
|
|
169
178
|
"EVO" => DiceTable::Table.from_i18n("FutariSousa.table.EVO", locale),
|
|
170
179
|
"EVF" => DiceTable::Table.from_i18n("FutariSousa.table.EVF", locale),
|
|
171
180
|
"EVB" => DiceTable::Table.from_i18n("FutariSousa.table.EVB", locale),
|
|
181
|
+
"EVL" => DiceTable::Table.from_i18n("FutariSousa.table.EVL", locale),
|
|
182
|
+
"EVZ" => DiceTable::Table.from_i18n("FutariSousa.table.EVZ", locale),
|
|
183
|
+
"EVR" => DiceTable::Table.from_i18n("FutariSousa.table.EVR", locale),
|
|
172
184
|
"OBT" => DiceTable::D66Table.from_i18n("FutariSousa.table.OBT", locale),
|
|
173
185
|
"ACT" => DiceTable::Table.from_i18n("FutariSousa.table.ACT", locale),
|
|
174
186
|
"EWT" => DiceTable::Table.from_i18n("FutariSousa.table.EWT", locale),
|
|
@@ -183,6 +195,7 @@ module BCDice
|
|
|
183
195
|
"BT" => DiceTable::Table.from_i18n("FutariSousa.table.BT", locale),
|
|
184
196
|
"GRT" => DiceTable::D66Table.from_i18n("FutariSousa.table.GRT", locale),
|
|
185
197
|
"MIT" => DiceTable::D66Table.from_i18n("FutariSousa.table.MIT", locale),
|
|
198
|
+
"MITE" => DiceTable::Table.from_i18n("FutariSousa.table.MITE", locale),
|
|
186
199
|
"JBT66" => DiceTable::D66Table.from_i18n("FutariSousa.table.JBT66", locale),
|
|
187
200
|
"JBT10" => DiceTable::Table.from_i18n("FutariSousa.table.JBT10", locale),
|
|
188
201
|
"FST66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FST66", locale),
|
|
@@ -191,6 +204,19 @@ module BCDice
|
|
|
191
204
|
"LDT10" => DiceTable::Table.from_i18n("FutariSousa.table.LDT10", locale),
|
|
192
205
|
"FLT66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FLT66", locale),
|
|
193
206
|
"FLT10" => DiceTable::Table.from_i18n("FutariSousa.table.FLT10", locale),
|
|
207
|
+
"FLTL66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FLTL66", locale),
|
|
208
|
+
"FLTD66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FLTD66", locale),
|
|
209
|
+
"FLTRA" => DiceTable::Table.from_i18n("FutariSousa.table.FLTRA", locale),
|
|
210
|
+
"FLTF66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FLTF66", locale),
|
|
211
|
+
"FLTB66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FLTB66", locale),
|
|
212
|
+
"FLTH66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FLTH66", locale),
|
|
213
|
+
"FLTS66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FLTS66", locale),
|
|
214
|
+
"FLTA66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FLTA66", locale),
|
|
215
|
+
"FLTW66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FLTW66", locale),
|
|
216
|
+
"FLTC66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FLTC66", locale),
|
|
217
|
+
"FLTU66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FLTU66", locale),
|
|
218
|
+
"FLTO66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FLTO66", locale),
|
|
219
|
+
"FLTI66" => DiceTable::D66Table.from_i18n("FutariSousa.table.FLTI66", locale),
|
|
194
220
|
"NCT66" => DiceTable::D66Table.from_i18n("FutariSousa.table.NCT66", locale),
|
|
195
221
|
"NCT10" => DiceTable::Table.from_i18n("FutariSousa.table.NCT10", locale),
|
|
196
222
|
}
|
|
@@ -35,9 +35,9 @@ module BCDice
|
|
|
35
35
|
|
|
36
36
|
def replace_text(string)
|
|
37
37
|
string
|
|
38
|
-
.gsub(/(\d+)GA(\d+)([
|
|
38
|
+
.gsub(/(\d+)GA(\d+)([+-][+\-\d]+)/) { "#{Regexp.last_match(1)}R6#{Regexp.last_match(3)}>=#{Regexp.last_match(2)}[1]" }
|
|
39
39
|
.gsub(/(\d+)GA(\d+)/) { "#{Regexp.last_match(1)}R6>=#{Regexp.last_match(2)}[1]" }
|
|
40
|
-
.gsub(/(\d+)G(\d+)([
|
|
40
|
+
.gsub(/(\d+)G(\d+)([+-][+\-\d]+)/) { "#{Regexp.last_match(1)}R6#{Regexp.last_match(3)}>=#{Regexp.last_match(2)}[0]" }
|
|
41
41
|
.gsub(/(\d+)G(\d+)/) { "#{Regexp.last_match(1)}R6>=#{Regexp.last_match(2)}[0]" }
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BCDice
|
|
4
|
+
module GameSystem
|
|
5
|
+
class GhostLive < Base
|
|
6
|
+
# ゲームシステムの識別子
|
|
7
|
+
ID = 'GhostLive'
|
|
8
|
+
|
|
9
|
+
# ゲームシステム名
|
|
10
|
+
NAME = '実況ゴーストライヴ'
|
|
11
|
+
|
|
12
|
+
# ゲームシステム名の読みがな
|
|
13
|
+
SORT_KEY = 'しつきようこおすとらいふ'
|
|
14
|
+
|
|
15
|
+
# ダイスボットの使い方
|
|
16
|
+
HELP_MESSAGE = <<~MESSAGE
|
|
17
|
+
■追加目標表(p11)
|
|
18
|
+
ATT, AdditionalTargetTable
|
|
19
|
+
|
|
20
|
+
■種別:地縛霊(p26)
|
|
21
|
+
□A.霊障リスト
|
|
22
|
+
JHA, JibakuHauntA
|
|
23
|
+
□B.霊障効果リスト
|
|
24
|
+
JHB, JibakuHauntB
|
|
25
|
+
|
|
26
|
+
■種別:シャイな幽霊(p27)
|
|
27
|
+
□A.霊障リスト
|
|
28
|
+
SHA, ShyHauntA
|
|
29
|
+
□B.霊障効果リスト
|
|
30
|
+
SHB, ShyHauntB
|
|
31
|
+
|
|
32
|
+
■種別:ぐちゃぐちゃ(p28)
|
|
33
|
+
□A.霊障リスト
|
|
34
|
+
GHA, GuchaHauntA
|
|
35
|
+
□B.霊障効果リスト
|
|
36
|
+
GHB, GuchaHauntB
|
|
37
|
+
MESSAGE
|
|
38
|
+
|
|
39
|
+
def eval_game_system_specific_command(command)
|
|
40
|
+
command = ALIAS[command] || command
|
|
41
|
+
roll_tables(command, TABLES)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
TABLES = {
|
|
45
|
+
"AdditionalTargetTable" => DiceTable::Table.new(
|
|
46
|
+
"追加目標表",
|
|
47
|
+
"1D6",
|
|
48
|
+
[
|
|
49
|
+
"オバケを撮影する。(依頼主:専門家/報酬:1L)",
|
|
50
|
+
"誰かひとりが霊障を[サイクル数]回受ける。(依頼主:専門家/報酬:[サイクル数]L)",
|
|
51
|
+
"誰かひとりが[精神力]を10以下の状態で帰る。(依頼主:専門家/報酬:3L)",
|
|
52
|
+
"[精神力]の平均が20以下の状態で帰る。(依頼主:リスナー/報酬:[視聴回数]を10倍)",
|
|
53
|
+
"全員がスマホ以外の[アイテム]を1個だけ持ち込んで生還する。(依頼主:リスナー/報酬:[視聴回数]を10倍)",
|
|
54
|
+
"すべての[回収品]を集める。(依頼主:専門家/報酬:5L)",
|
|
55
|
+
]
|
|
56
|
+
),
|
|
57
|
+
"JibakuHauntA" => DiceTable::Table.new(
|
|
58
|
+
"地縛霊:霊障リスト",
|
|
59
|
+
"1D6",
|
|
60
|
+
[
|
|
61
|
+
"隙間――家具の隙間、扉の隙間、そんな暗がりから視線を感じる。",
|
|
62
|
+
"腐臭――吐き気を催すような、下水に似た臭いが漂ってくる。",
|
|
63
|
+
"吐息――「ハァ……」耳元に、やけに湿った吐息が吹きかけられる。",
|
|
64
|
+
"足音――立ち止まる度に、ひとつ多く足音が響く。誰か、いる……?",
|
|
65
|
+
"背後――振り向いても、そこには誰もいない。それなのに、ずっと後ろに気配を感じる。",
|
|
66
|
+
"鏡――鏡に背を向けた瞬間、あり得ない強さでそちらへ引き寄せられた。肩には手の形のアザができている。",
|
|
67
|
+
]
|
|
68
|
+
),
|
|
69
|
+
"JibakuHauntB" => DiceTable::Table.new(
|
|
70
|
+
"地縛霊:霊障効果リスト",
|
|
71
|
+
"1D6",
|
|
72
|
+
[
|
|
73
|
+
"[精神力]減少:[1D2+PC人数]点/[視聴回数]増加:とくになし/特殊効果:とくになし",
|
|
74
|
+
"[精神力]減少:[1D4+PC人数]点/[視聴回数]増加:とくになし/特殊効果:とくになし",
|
|
75
|
+
"[精神力]減少:[1D6+PC人数]点/[視聴回数]増加:2倍/特殊効果:とくになし",
|
|
76
|
+
"[精神力]減少:[1D10+PC人数]点/[視聴回数]増加:3倍/特殊効果:シーンに登場しているPCの[アイテム]を1つ破壊する。",
|
|
77
|
+
"[精神力]減少:[1D20+PC人数]点/[視聴回数]増加:5倍/特殊効果:シーンに登場しているPCのスマホを破壊する。",
|
|
78
|
+
"[精神力]減少:[1D100+PC人数]点/[視聴回数]増加:10倍/特殊効果:シーンに登場しているPCのスマホを破壊する。",
|
|
79
|
+
]
|
|
80
|
+
),
|
|
81
|
+
"ShyHauntA" => DiceTable::Table.new(
|
|
82
|
+
"シャイな幽霊:霊障リスト",
|
|
83
|
+
"1D6",
|
|
84
|
+
[
|
|
85
|
+
"倦怠感――歩くのも辛いくらいの倦怠感。生きているのも辛い。",
|
|
86
|
+
"ラップ音――弾けるような、叩くような音が連続して聞こえる。",
|
|
87
|
+
"空飛ぶ皿――棚に収まっていた食器が、不意に飛び出し、けたたましい音を立てて砕けていく。",
|
|
88
|
+
"頭痛――頭が、割れそうに痛い。小さな物音ですら頭に響いてくる。",
|
|
89
|
+
"点滅――灯りが明滅する。……あれ、ここ電気通ってたっけ?",
|
|
90
|
+
"血文字――壁に、床に、赤⿊い液体が滲み出す。それは文字を形作った。「か え れ」",
|
|
91
|
+
]
|
|
92
|
+
),
|
|
93
|
+
"ShyHauntB" => DiceTable::Table.new(
|
|
94
|
+
"シャイな幽霊:霊障効果リスト",
|
|
95
|
+
"1D6",
|
|
96
|
+
[
|
|
97
|
+
"[精神力]減少:[2+PC人数]点/[視聴回数]増加:とくになし/特殊効果:とくになし",
|
|
98
|
+
"[精神力]減少:[4+PC人数]点/[視聴回数]増加:2倍/特殊効果:シーンに登場しているPCがふたりの場合、追加で[精神力]を2減少させる。",
|
|
99
|
+
"[精神力]減少:[6+PC人数]点/[視聴回数]増加:3倍/特殊効果:シーンに登場しているPCがひとりの場合、追加で[精神力]を4減少させる。",
|
|
100
|
+
"[精神力]減少:[10+PC人数]点/[視聴回数]増加:5倍/特殊効果:シーンに登場しているPCがふたりの場合、追加で[精神力]を6減少させる。",
|
|
101
|
+
"[精神力]減少:[20+PC人数]点/[視聴回数]増加:10倍/特殊効果:シーンに登場しているPCがひとりの場合、追加で[精神力]を2減少させる。",
|
|
102
|
+
"[精神力]減少:[40+PC人数]点/[視聴回数]増加:20倍/特殊効果:シーンに登場しているPCのスマホを破壊する。",
|
|
103
|
+
]
|
|
104
|
+
),
|
|
105
|
+
"GuchaHauntA" => DiceTable::Table.new(
|
|
106
|
+
"ぐちゃぐちゃ:霊障リスト",
|
|
107
|
+
"1D6",
|
|
108
|
+
[
|
|
109
|
+
"走る人形――ひび割れた人形が落ちている。一瞬視線をそらした瞬間、それはありえない動きで走り去っていった。",
|
|
110
|
+
"血痕――天井から血が滴ってくる。その量は、おおよそ人一人分……いや、それ以上だ。",
|
|
111
|
+
"着信――スマホの着信音が鳴る。こんな時に誰が――表示されていたのは、死んだはずの知り合いの名前だった。",
|
|
112
|
+
"自分に似た他人――自分にそっくりな人が目の前に立っていた、気がする。",
|
|
113
|
+
"衝撃――誰かに思いっきり押された気がしたのに誰もいない。",
|
|
114
|
+
"記憶がない――数分間のことを何も覚えてない。コメント欄がリスナーの心配する声でいっぱいだ。いったい何が……?",
|
|
115
|
+
]
|
|
116
|
+
),
|
|
117
|
+
"GuchaHauntB" => DiceTable::Table.new(
|
|
118
|
+
"ぐちゃぐちゃ:霊障効果リスト",
|
|
119
|
+
"1D6",
|
|
120
|
+
[
|
|
121
|
+
"[精神力]減少:[5+PC人数]点/[視聴回数]増加:2倍/特殊効果:とくになし",
|
|
122
|
+
"[精神力]減少:[10+PC人数]点/[視聴回数]増加:3倍/特殊効果:とくになし",
|
|
123
|
+
"[精神力]減少:[2D10+PC人数]点/[視聴回数]増加:4倍/特殊効果:シーンに登場しているPCがふたりの場合、追加で[精神力]を5減少させる。",
|
|
124
|
+
"[精神力]減少:[3D10+PC人数]点/[視聴回数]増加:5倍/特殊効果:シーンに登場しているPCがひとりの場合、[アイテム]をランダムに1つ壊す。",
|
|
125
|
+
"[精神力]減少:[1D100+PC人数]点/[視聴回数]増加:10倍/特殊効果:シーンに登場しているPCのスマホを破壊する。",
|
|
126
|
+
"[精神力]減少:[1D100+10+PC人数]点/[視聴回数]増加:20倍/特殊効果:すべてのPCのスマホを破壊する。",
|
|
127
|
+
]
|
|
128
|
+
),
|
|
129
|
+
}.transform_keys(&:upcase).freeze
|
|
130
|
+
|
|
131
|
+
ALIAS = {
|
|
132
|
+
"ATT" => "AdditionalTargetTable",
|
|
133
|
+
"JHA" => "JibakuHauntA",
|
|
134
|
+
"JHB" => "JibakuHauntB",
|
|
135
|
+
"SHA" => "ShyHauntA",
|
|
136
|
+
"SHB" => "ShyHauntB",
|
|
137
|
+
"GHA" => "GuchaHauntA",
|
|
138
|
+
"GHB" => "GuchaHauntB",
|
|
139
|
+
}.transform_values(&:upcase).freeze
|
|
140
|
+
|
|
141
|
+
register_prefix(TABLES.keys, ALIAS.keys)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -14,11 +14,13 @@ module BCDice
|
|
|
14
14
|
|
|
15
15
|
# ダイスボットの使い方
|
|
16
16
|
HELP_MESSAGE = <<~MESSAGETEXT
|
|
17
|
-
・判定 GS(x)>=y
|
|
17
|
+
・判定 GS(x)@c#f>=y
|
|
18
18
|
2d6の判定を行い、達成値を出力します。
|
|
19
|
-
xは基準値、y
|
|
19
|
+
xは基準値、yは目標値、cは大成功の下限、fは大失敗の上限です。いずれも省略可能です。
|
|
20
|
+
cが未指定の場合には c=12 、fが未指定の場合には f=2 となります。
|
|
20
21
|
yが設定されている場合、大成功/成功/失敗/大失敗を自動判定します。
|
|
21
22
|
例)GS>=12 GS>10 GS(10)>14 GS+10>=15 GS10>=15 GS(10) GS+10 GS10 GS
|
|
23
|
+
GS@10 GS@10#3 GS#3@10
|
|
22
24
|
|
|
23
25
|
・祈念 MCPI(n)$m
|
|
24
26
|
祈念を行います。
|
|
@@ -62,15 +64,26 @@ module BCDice
|
|
|
62
64
|
end
|
|
63
65
|
|
|
64
66
|
def getCheckResult(command)
|
|
65
|
-
m = /^GS([-+]?\d+)?((>=?)(\d+))?$/i.match(command)
|
|
67
|
+
m = /^GS([-+]?\d+)?(?:(?:([@#])([-+]?\d+))(?:([@#])([-+]?\d+))?)?(?:(>=?)(\d+))?$/i.match(command)
|
|
66
68
|
unless m
|
|
67
69
|
return nil
|
|
68
70
|
end
|
|
69
71
|
|
|
70
72
|
basis = m[1].to_i # 基準値
|
|
71
|
-
target = m[
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
target = m[7].to_i
|
|
74
|
+
cmp_op = m[6]
|
|
75
|
+
without_compare = cmp_op.nil?
|
|
76
|
+
|
|
77
|
+
option1 = m[2]
|
|
78
|
+
option1_value = m[3]
|
|
79
|
+
option2 = m[4]
|
|
80
|
+
option2_param = m[5]
|
|
81
|
+
|
|
82
|
+
if option1 && option1 == option2
|
|
83
|
+
return nil
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
threshold_critical, threshold_fumble = calc_threshold(option1, option1_value, option2, option2_param)
|
|
74
87
|
|
|
75
88
|
dice_list = @randomizer.roll_barabara(2, 6)
|
|
76
89
|
total = dice_list.sum()
|
|
@@ -78,8 +91,8 @@ module BCDice
|
|
|
78
91
|
|
|
79
92
|
achievement = basis + total # 達成値
|
|
80
93
|
|
|
81
|
-
fumble =
|
|
82
|
-
critical =
|
|
94
|
+
fumble = total <= threshold_fumble
|
|
95
|
+
critical = total >= threshold_critical
|
|
83
96
|
|
|
84
97
|
result = " > #{resultStr(achievement, target, cmp_op, fumble, critical)}"
|
|
85
98
|
if without_compare && !fumble && !critical
|
|
@@ -90,6 +103,15 @@ module BCDice
|
|
|
90
103
|
return "(#{command}) > #{basis_str}#{total}[#{diceText}] > #{achievement}#{result}"
|
|
91
104
|
end
|
|
92
105
|
|
|
106
|
+
CRITICAL = 12
|
|
107
|
+
FUMBLE = 2
|
|
108
|
+
|
|
109
|
+
def calc_threshold(option1, option1_value, _option2, option2_value)
|
|
110
|
+
critical, fumble = option1 == "@" ? [option1_value, option2_value] : [option2_value, option1_value]
|
|
111
|
+
|
|
112
|
+
return [critical&.to_i || CRITICAL, fumble&.to_i || FUMBLE]
|
|
113
|
+
end
|
|
114
|
+
|
|
93
115
|
def murmurChantPrayInvoke(command)
|
|
94
116
|
m = /^MCPI(\+?\d+)?\$(\d+)$/i.match(command)
|
|
95
117
|
unless m
|