bcdice 3.7.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 +31 -0
- data/i18n/Arianrhod/ja_jp.yml +3 -0
- data/i18n/Emoklore/ja_jp.yml +7 -0
- 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 +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/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/BeastBindTrinity.rb +1 -1
- data/lib/bcdice/game_system/BeginningIdol.rb +2 -2
- data/lib/bcdice/game_system/BeginningIdol2022.rb +2 -2
- 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 +1 -0
- data/lib/bcdice/game_system/GURPS.rb +1 -1
- data/lib/bcdice/game_system/GehennaAn.rb +2 -2
- data/lib/bcdice/game_system/HunterTheReckoning5th.rb +152 -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/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/Warhammer4.rb +4 -0
- data/lib/bcdice/game_system/WorldOfDarkness.rb +17 -9
- 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/sword_world/rating_parser.rb +1 -1
- data/lib/bcdice/game_system.rb +9 -0
- data/lib/bcdice/version.rb +1 -1
- metadata +17 -3
@@ -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
|
|
@@ -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,152 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BCDice
|
4
|
+
module GameSystem
|
5
|
+
class HunterTheReckoning5th < Base
|
6
|
+
# ゲームシステムの識別子
|
7
|
+
ID = 'HunterTheReckoning5th'
|
8
|
+
|
9
|
+
# ゲームシステム名
|
10
|
+
NAME = 'Hunter: The Reckoning 5th Edition'
|
11
|
+
|
12
|
+
# ゲームシステム名の読みがな
|
13
|
+
SORT_KEY = 'はんあたされこにんく5'
|
14
|
+
|
15
|
+
# ダイスボットの使い方
|
16
|
+
HELP_MESSAGE = <<~MESSAGETEXT
|
17
|
+
・判定コマンド(nHRFx+x)
|
18
|
+
注意:難易度は必要成功数を表す
|
19
|
+
|
20
|
+
難易度指定:成功数のカウント、判定成功と失敗、Critical処理、Critical Winのチェックを行う
|
21
|
+
(Desperationダイスがある場合)OverreachとDespairの発生チェックを行う
|
22
|
+
例) (難易度)HRF(通常ダイス)+(Desperationダイス)
|
23
|
+
(難易度)HRF(通常ダイス)
|
24
|
+
|
25
|
+
難易度省略:成功数のカウント、判定失敗、Critical処理、(Desperationダイスがある場合)Despairチェックを行う
|
26
|
+
判定成功、Overreachのチェックを行わない
|
27
|
+
Critical Win、(Desperationダイスがある場合)Despair、Overreachのヒントを出力
|
28
|
+
例) HRF(通常ダイス)+(Desperationダイス)
|
29
|
+
HRF(通常ダイス)
|
30
|
+
|
31
|
+
難易度0指定:全てのチェックを行わない
|
32
|
+
例) 0HRF(通常ダイス)+(Desperationダイス)
|
33
|
+
0HRF(通常ダイス)
|
34
|
+
|
35
|
+
MESSAGETEXT
|
36
|
+
|
37
|
+
DIFFICULTY_INDEX = 1
|
38
|
+
DICE_POOL_INDEX = 3
|
39
|
+
DESPERATION_DICE_INDEX = 5
|
40
|
+
|
41
|
+
# 難易度に指定可能な特殊値
|
42
|
+
NOT_CHECK_SUCCESS = -1 # 判定成功にかかわるチェックを行わない(判定失敗に関わるチェックは行う)
|
43
|
+
|
44
|
+
# ダイスボットで使用するコマンドを配列で列挙する
|
45
|
+
register_prefix('\d*HRF')
|
46
|
+
|
47
|
+
def eval_game_system_specific_command(command)
|
48
|
+
m = /\A(\d+)?(HRF)(\d+)(\+(\d+))?$/.match(command)
|
49
|
+
unless m
|
50
|
+
return ''
|
51
|
+
end
|
52
|
+
|
53
|
+
dice_pool = m[DICE_POOL_INDEX].to_i
|
54
|
+
dice_text, success_dice, ten_dice, = make_dice_roll(dice_pool)
|
55
|
+
result_text = "(#{dice_pool}D10"
|
56
|
+
|
57
|
+
desperaton_dice_pool = m[DESPERATION_DICE_INDEX]&.to_i
|
58
|
+
if desperaton_dice_pool
|
59
|
+
desperaton_dice_text, desperaton_success_dice, desperaton_ten_dice, desperaton_botch_dice = make_dice_roll(desperaton_dice_pool)
|
60
|
+
|
61
|
+
ten_dice += desperaton_ten_dice
|
62
|
+
success_dice += desperaton_success_dice
|
63
|
+
|
64
|
+
result_text = "#{result_text}+#{desperaton_dice_pool}D10) > [#{dice_text}]+[#{desperaton_dice_text}] "
|
65
|
+
else
|
66
|
+
desperaton_ten_dice = 0
|
67
|
+
desperaton_botch_dice = 0
|
68
|
+
result_text = "#{result_text}) > [#{dice_text}] "
|
69
|
+
end
|
70
|
+
|
71
|
+
success_dice += get_critical_success(ten_dice)
|
72
|
+
|
73
|
+
difficulty = m[DIFFICULTY_INDEX] ? m[DIFFICULTY_INDEX].to_i : NOT_CHECK_SUCCESS
|
74
|
+
|
75
|
+
return get_roll_result(result_text, success_dice, ten_dice, desperaton_ten_dice, desperaton_botch_dice, difficulty)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def get_roll_result(result_text, success_dice, ten_dice, _desperaton_ten_dice, desperaton_botch_dice, difficulty)
|
81
|
+
result_text = "#{result_text} 成功数=#{success_dice}"
|
82
|
+
is_critical = ten_dice >= 2
|
83
|
+
desperation_result = ""
|
84
|
+
|
85
|
+
if difficulty > 0
|
86
|
+
result_text = "#{result_text} 難易度=#{difficulty}"
|
87
|
+
|
88
|
+
if success_dice >= difficulty
|
89
|
+
result_text = "#{result_text} 差分=#{success_dice - difficulty}"
|
90
|
+
|
91
|
+
if desperaton_botch_dice > 0
|
92
|
+
desperation_result = " [Overreach or Despair?]"
|
93
|
+
end
|
94
|
+
|
95
|
+
if is_critical
|
96
|
+
return Result.critical("#{result_text}:判定成功! [Critical Win]#{desperation_result}")
|
97
|
+
else
|
98
|
+
return Result.success("#{result_text}:判定成功!#{desperation_result}")
|
99
|
+
end
|
100
|
+
|
101
|
+
else
|
102
|
+
if desperaton_botch_dice > 0
|
103
|
+
return Result.fumble("#{result_text}:判定失敗! [Despair]")
|
104
|
+
end
|
105
|
+
|
106
|
+
return Result.failure("#{result_text}:判定失敗!")
|
107
|
+
end
|
108
|
+
elsif difficulty < 0
|
109
|
+
if success_dice == 0
|
110
|
+
if desperaton_botch_dice > 0
|
111
|
+
return Result.fumble("#{result_text}:判定失敗! [Despair]")
|
112
|
+
end
|
113
|
+
|
114
|
+
return Result.failure("#{result_text}:判定失敗!")
|
115
|
+
else
|
116
|
+
if desperaton_botch_dice > 0
|
117
|
+
result_text = "#{result_text}\n 判定失敗なら [Despair]"
|
118
|
+
desperation_result = " [Overreach or Despair?]"
|
119
|
+
end
|
120
|
+
|
121
|
+
if is_critical
|
122
|
+
result_text = "#{result_text}\n 判定成功なら [Critical Win]"
|
123
|
+
elsif desperaton_botch_dice > 0
|
124
|
+
result_text = "#{result_text}\n 判定成功なら"
|
125
|
+
end
|
126
|
+
|
127
|
+
return "#{result_text}#{desperation_result}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# 難易度0指定(=全ての判定チェックを行わない)
|
132
|
+
return result_text.to_s
|
133
|
+
end
|
134
|
+
|
135
|
+
def get_critical_success(ten_dice)
|
136
|
+
# 10の目が2個毎に追加2成功
|
137
|
+
return ((ten_dice / 2) * 2)
|
138
|
+
end
|
139
|
+
|
140
|
+
def make_dice_roll(dice_pool)
|
141
|
+
dice_list = @randomizer.roll_barabara(dice_pool, 10)
|
142
|
+
|
143
|
+
dice_text = dice_list.join(',')
|
144
|
+
success_dice = dice_list.count { |x| x >= 6 }
|
145
|
+
ten_dice = dice_list.count(10)
|
146
|
+
botch_dice = dice_list.count(1)
|
147
|
+
|
148
|
+
return dice_text, success_dice, ten_dice, botch_dice
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bcdice/dice_table/table'
|
4
|
+
|
5
|
+
module BCDice
|
6
|
+
module GameSystem
|
7
|
+
class NobunagasBlackCastle < Base
|
8
|
+
# ゲームシステムの識別子
|
9
|
+
ID = 'NobunagasBlackCastle'
|
10
|
+
|
11
|
+
# ゲームシステム名
|
12
|
+
NAME = '信長の黒い城'
|
13
|
+
|
14
|
+
# ゲームシステム名の読みがな
|
15
|
+
SORT_KEY = 'のふなかのくろいしろ'
|
16
|
+
|
17
|
+
# ダイスボットの使い方
|
18
|
+
HELP_MESSAGE = <<~INFO_MESSAGETEXT
|
19
|
+
■判定 sDRt s: 能力値 t:目標値
|
20
|
+
|
21
|
+
例)+3DR12: 能力値+3、DR12で1d20を振って、その結果を表示(クリティカル・ファンブルも表示)
|
22
|
+
|
23
|
+
■イニシアティヴ INS
|
24
|
+
|
25
|
+
例)INS: 1d6を振って、イニシアティヴの結果を表示(PC先行を成功として表示)
|
26
|
+
|
27
|
+
■NPC能力値作成 NPCST
|
28
|
+
|
29
|
+
例)NPCST: 3d6を4回振って、各能力値とHPを表示
|
30
|
+
|
31
|
+
|
32
|
+
■各種表
|
33
|
+
|
34
|
+
・遭遇反応表(ERT)
|
35
|
+
・武器表(SWT)/その他の奇妙な武器表(OSWT)
|
36
|
+
・鎧表(ART)
|
37
|
+
|
38
|
+
INFO_MESSAGETEXT
|
39
|
+
|
40
|
+
def initialize(command)
|
41
|
+
super(command)
|
42
|
+
|
43
|
+
@sort_add_dice = true
|
44
|
+
@d66_sort_type = D66SortType::NO_SORT
|
45
|
+
end
|
46
|
+
|
47
|
+
def eval_game_system_specific_command(command)
|
48
|
+
resolute_action(command) || resolute_initiative(command) || roll_tables(command, TABLES) || make_npc_status(command)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def result_dr(total, dice_total, target)
|
54
|
+
if dice_total <= 1
|
55
|
+
Result.fumble("ファンブル")
|
56
|
+
elsif dice_total >= 20
|
57
|
+
Result.critical("クリティカル")
|
58
|
+
elsif total >= target
|
59
|
+
Result.success("成功")
|
60
|
+
else
|
61
|
+
Result.failure("失敗")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# DR判定
|
66
|
+
# @param [String] command
|
67
|
+
# @return [Result]
|
68
|
+
def resolute_action(command)
|
69
|
+
m = /^([+-]?\d*)DR(\d+)$/.match(command)
|
70
|
+
return nil unless m
|
71
|
+
|
72
|
+
num_status = m[1].to_i
|
73
|
+
num_target = m[2].to_i
|
74
|
+
|
75
|
+
total = @randomizer.roll_once(20)
|
76
|
+
total_status = total.to_s + with_symbol(num_status)
|
77
|
+
result = result_dr(total + num_status, total, num_target)
|
78
|
+
|
79
|
+
sequence = [
|
80
|
+
"(#{command})",
|
81
|
+
total_status,
|
82
|
+
total + num_status,
|
83
|
+
result.text,
|
84
|
+
]
|
85
|
+
|
86
|
+
result.text = sequence.join(" > ")
|
87
|
+
return result
|
88
|
+
end
|
89
|
+
|
90
|
+
def with_symbol(number)
|
91
|
+
if number == 0
|
92
|
+
return "+0"
|
93
|
+
elsif number > 0
|
94
|
+
return "+#{number}"
|
95
|
+
else
|
96
|
+
return number.to_s
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# イニシアティヴ判定
|
101
|
+
# @param [String] command
|
102
|
+
# @return [Result]
|
103
|
+
def resolute_initiative(command)
|
104
|
+
unless command == "INS"
|
105
|
+
return nil
|
106
|
+
end
|
107
|
+
|
108
|
+
total = @randomizer.roll_once(6)
|
109
|
+
result =
|
110
|
+
if total >= 4
|
111
|
+
Result.success("PC先行")
|
112
|
+
else
|
113
|
+
Result.failure("敵先行")
|
114
|
+
end
|
115
|
+
|
116
|
+
result.text = "(#{command}) > #{total} > #{result.text}"
|
117
|
+
return result
|
118
|
+
end
|
119
|
+
|
120
|
+
# NPC能力値作成
|
121
|
+
# @param [String] command
|
122
|
+
# @return [String]
|
123
|
+
def make_npc_status(command)
|
124
|
+
unless command == "NPCST"
|
125
|
+
return nil
|
126
|
+
end
|
127
|
+
|
128
|
+
pre = @randomizer.roll_sum(3, 6)
|
129
|
+
agi = @randomizer.roll_sum(3, 6)
|
130
|
+
str = @randomizer.roll_sum(3, 6)
|
131
|
+
tgh = @randomizer.roll_sum(3, 6)
|
132
|
+
hpd = @randomizer.roll_once(8)
|
133
|
+
hp = hpd + calc_status(tgh)
|
134
|
+
hp = 1 if hp < 1
|
135
|
+
|
136
|
+
text = [
|
137
|
+
"心#{with_symbol(calc_status(pre))}(#{pre})",
|
138
|
+
"技#{with_symbol(calc_status(agi))}(#{agi})",
|
139
|
+
"体#{with_symbol(calc_status(str))}(#{str})",
|
140
|
+
"耐久#{with_symbol(calc_status(tgh))}(#{tgh})",
|
141
|
+
"HP#{hp}(#{hpd})",
|
142
|
+
].join(", ")
|
143
|
+
|
144
|
+
return "(#{command}) > #{text}"
|
145
|
+
end
|
146
|
+
|
147
|
+
def calc_status(st)
|
148
|
+
if st <= 4
|
149
|
+
return -3
|
150
|
+
elsif st <= 6
|
151
|
+
return -2
|
152
|
+
elsif st <= 8
|
153
|
+
return -1
|
154
|
+
elsif st <= 12
|
155
|
+
return 0
|
156
|
+
elsif st <= 14
|
157
|
+
return 1
|
158
|
+
elsif st <= 16
|
159
|
+
return 2
|
160
|
+
elsif st <= 20
|
161
|
+
return 3
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# 各種表
|
166
|
+
|
167
|
+
TABLES = {
|
168
|
+
'OSWT' => DiceTable::Table.new(
|
169
|
+
'その他の奇妙な武器表',
|
170
|
+
'1D10',
|
171
|
+
[
|
172
|
+
'六尺棒(D4)',
|
173
|
+
'手槍(D4)',
|
174
|
+
'弓矢(D6)',
|
175
|
+
'鉄扇(D4)',
|
176
|
+
'大鉞(D8)',
|
177
|
+
'吹き矢(D2)+感染',
|
178
|
+
'鞭(D3)',
|
179
|
+
'熊手(D4)',
|
180
|
+
'石つぶて(D3)',
|
181
|
+
'丸太(D4)',
|
182
|
+
]
|
183
|
+
),
|
184
|
+
'SWT' => DiceTable::Table.new(
|
185
|
+
'武器表',
|
186
|
+
'1D12',
|
187
|
+
[
|
188
|
+
'尖らせた骨の杭(D3)',
|
189
|
+
'竹槍(D4)',
|
190
|
+
'百姓から奪った鍬(D4)',
|
191
|
+
'脇差し(D4)',
|
192
|
+
'手裏剣 D6本(D4)',
|
193
|
+
'刀(D6)',
|
194
|
+
'鎖鎌(D6)',
|
195
|
+
'太刀(D8)',
|
196
|
+
'種子島銃(2D6) 弾丸(心+5)発',
|
197
|
+
'大槍(D8)',
|
198
|
+
'爆裂弾(D4) 心+3発',
|
199
|
+
'斬馬刀(D10)',
|
200
|
+
]
|
201
|
+
),
|
202
|
+
'ART' => DiceTable::Table.new(
|
203
|
+
'鎧表',
|
204
|
+
'1D6',
|
205
|
+
[
|
206
|
+
'防具は、何もない',
|
207
|
+
'防具は、何もない',
|
208
|
+
'部分鎧(腹巻き) -D2ダメージ',
|
209
|
+
'お貸し具足 -D3ダメージ',
|
210
|
+
'武者鎧 -D4ダメージ',
|
211
|
+
'大鎧 -D6ダメージ',
|
212
|
+
]
|
213
|
+
),
|
214
|
+
# 無理に高度なことをしなくても、表は展開して実装しても動く
|
215
|
+
'ERT' => DiceTable::Table.new(
|
216
|
+
'遭遇反応表',
|
217
|
+
'2D6',
|
218
|
+
[
|
219
|
+
'お前ら、殺す!',
|
220
|
+
'お前ら、殺す!',
|
221
|
+
'憎悪の視線で睨んでくる。すきを見せれば、攻撃してくる。',
|
222
|
+
'憎悪の視線で睨んでくる。すきを見せれば、攻撃してくる。',
|
223
|
+
'憎悪の視線で睨んでくる。すきを見せれば、攻撃してくる。',
|
224
|
+
'警戒はしているが、特に、戦闘は望んでいない。怒らせなければ、自分たちの目的に沿って動く。',
|
225
|
+
'警戒はしているが、特に、戦闘は望んでいない。怒らせなければ、自分たちの目的に沿って動く。',
|
226
|
+
'中立。何かを与えたり、取引の材料を提示したりできれば、交渉できそうだ。',
|
227
|
+
'中立。何かを与えたり、取引の材料を提示したりできれば、交渉できそうだ。',
|
228
|
+
'好意的に会話できそうだ。向こうも取引したがっている。',
|
229
|
+
'好意的に会話できそうだ。向こうも取引したがっている。',
|
230
|
+
]
|
231
|
+
),
|
232
|
+
}.freeze
|
233
|
+
|
234
|
+
register_prefix('[+-]?\d*DR[\d]+', 'INS', 'NPCST', TABLES.keys)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|