bcdice 3.12.0 → 3.14.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 +72 -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/arithmetic/parser.rb +4 -2
- data/lib/bcdice/base.rb +1 -1
- data/lib/bcdice/command/parser.rb +4 -2
- data/lib/bcdice/common_command/add_dice/parser.rb +4 -2
- data/lib/bcdice/common_command/barabara_dice/parser.rb +4 -2
- data/lib/bcdice/common_command/calc/parser.rb +4 -2
- data/lib/bcdice/common_command/reroll_dice/parser.rb +4 -2
- data/lib/bcdice/common_command/tally_dice/parser.rb +4 -2
- data/lib/bcdice/common_command/upper_dice/parser.rb +4 -2
- data/lib/bcdice/dice_table/range_table.rb +24 -0
- data/lib/bcdice/game_system/Agnostos.rb +248 -0
- data/lib/bcdice/game_system/Airgetlamh.rb +1 -1
- data/lib/bcdice/game_system/Alsetto.rb +2 -2
- data/lib/bcdice/game_system/AniMalus.rb +261 -0
- data/lib/bcdice/game_system/Arianrhod_Korean.rb +30 -0
- data/lib/bcdice/game_system/ArknightsFan.rb +182 -0
- data/lib/bcdice/game_system/Avandner.rb +1 -1
- data/lib/bcdice/game_system/BBN.rb +1 -1
- data/lib/bcdice/game_system/BadLife.rb +3 -3
- data/lib/bcdice/game_system/BarnaKronika.rb +1 -1
- data/lib/bcdice/game_system/BlackJacket.rb +244 -0
- data/lib/bcdice/game_system/Chill3.rb +6 -6
- 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/DarkSouls.rb +1 -1
- data/lib/bcdice/game_system/DivineCharger.rb +841 -0
- data/lib/bcdice/game_system/Elric.rb +1 -1
- 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 +121 -0
- data/lib/bcdice/game_system/FutariSousa.rb +88 -8
- data/lib/bcdice/game_system/InfiniteFantasia.rb +4 -1
- data/lib/bcdice/game_system/Insane_Korean.rb +1 -1
- data/lib/bcdice/game_system/InvisibleLiar.rb +79 -0
- data/lib/bcdice/game_system/Irisbane.rb +1 -1
- data/lib/bcdice/game_system/KillDeathBusiness.rb +1 -1
- data/lib/bcdice/game_system/KizunaBullet.rb +240 -0
- data/lib/bcdice/game_system/KyokoShinshoku.rb +201 -0
- data/lib/bcdice/game_system/Liminal.rb +136 -0
- data/lib/bcdice/game_system/MetalHead.rb +1 -1
- data/lib/bcdice/game_system/MetalHeadExtream.rb +1 -1
- data/lib/bcdice/game_system/MonotoneMuseum.rb +14 -1
- data/lib/bcdice/game_system/NRR.rb +122 -0
- data/lib/bcdice/game_system/NSSQ.rb +1 -1
- data/lib/bcdice/game_system/NightWizard.rb +1 -1
- data/lib/bcdice/game_system/NightWizard3rd.rb +15 -2
- data/lib/bcdice/game_system/OneWayHeroics.rb +1 -1
- data/lib/bcdice/game_system/PastFutureParadox.rb +1238 -0
- data/lib/bcdice/game_system/Postman.rb +3 -3
- data/lib/bcdice/game_system/RecordOfSteam.rb +1 -1
- data/lib/bcdice/game_system/RuneQuestRoleplayingInGlorantha.rb +1 -1
- data/lib/bcdice/game_system/Ryutama.rb +4 -4
- data/lib/bcdice/game_system/ShuumatsuBargainWars.rb +203 -0
- data/lib/bcdice/game_system/Siren.rb +97 -0
- data/lib/bcdice/game_system/Skynauts.rb +1 -1
- data/lib/bcdice/game_system/SkynautsBouken.rb +45 -130
- data/lib/bcdice/game_system/Strave.rb +1 -1
- 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/TherapieSein.rb +1 -1
- data/lib/bcdice/game_system/TrailOfCthulhu.rb +139 -0
- data/lib/bcdice/game_system/TrinitySeven.rb +1 -1
- 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/VampireTheMasquerade5th.rb +12 -6
- data/lib/bcdice/game_system/Warhammer4.rb +124 -3
- data/lib/bcdice/game_system/WerewolfTheApocalypse5th.rb +12 -6
- data/lib/bcdice/game_system/Yotabana.rb +62 -0
- data/lib/bcdice/game_system/cthulhu7th/full_auto.rb +1 -1
- 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/sword_world/rating_parser.rb +4 -2
- data/lib/bcdice/game_system.rb +24 -0
- data/lib/bcdice/loader.rb +1 -1
- data/lib/bcdice/version.rb +1 -1
- metadata +55 -5
@@ -113,7 +113,7 @@ module BCDice
|
|
113
113
|
dice = 2 if dice < 2
|
114
114
|
dice = 12 if dice > 12
|
115
115
|
|
116
|
-
currentKey =
|
116
|
+
currentKey = (command.rate + round * command.rateup).clamp(0, keyMax)
|
117
117
|
debug("currentKey", currentKey)
|
118
118
|
rateValue = newRates[dice][currentKey]
|
119
119
|
debug("rateValue", rateValue)
|
@@ -0,0 +1,228 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BCDice
|
4
|
+
module GameSystem
|
5
|
+
class TensaiGunshiNiNaro < Base
|
6
|
+
# ゲームシステムの識別子
|
7
|
+
ID = 'TensaiGunshiNiNaro'
|
8
|
+
|
9
|
+
# ゲームシステム名
|
10
|
+
NAME = '天才軍師になろう'
|
11
|
+
|
12
|
+
# ゲームシステム名の読みがな
|
13
|
+
SORT_KEY = 'てんさいくんしになろう'
|
14
|
+
|
15
|
+
# ダイスボットの使い方
|
16
|
+
HELP_MESSAGE = <<~MESSAGETEXT
|
17
|
+
・行為判定
|
18
|
+
TN6…「有利」を得ていない場合、6面ダイスを2つ振って判定します。
|
19
|
+
TN10…「有利」を得ている場合、10面ダイスを2つ振って判定します。
|
20
|
+
不調 気づかぬうちの不満【C】…判定のダイス目が「4」でも判定に成功しません。数字の後ろに【C】をつけます。
|
21
|
+
例)TN6C
|
22
|
+
軍師スキル 〇〇サポート【S】…決戦フェイズの判定中「3」の出目を出しても判定に成功します。数字の後ろに【S】をつけます。
|
23
|
+
例)TN6S
|
24
|
+
英傑スキル/武人 煌めく刃【B】…決戦フェイズの判定中「3」の出目を出しても判定に成功となり、スペシャルが発生します。数字の後ろに【B】をつけます。
|
25
|
+
例)TN6B
|
26
|
+
英傑スキル/カリスマ 御身のためならば【Y】…「交流」「スカウト」の判定中「3」の出目を出しても判定に成功となり、スペシャルが発生します。数字の後ろに【Y】をつけます。
|
27
|
+
例)TN6Y
|
28
|
+
英傑スキル/英傑汎用 凄腕エージェント【A】…活動フェイズの判定中「3」の出目を出しても判定に成功となり、スペシャルが発生します。数字の後ろに【A】をつけます。
|
29
|
+
例)TN6A
|
30
|
+
数字の後ろに複数のコマンドを追加できます。
|
31
|
+
例)TN10CYA
|
32
|
+
・ダメージ計算 xDM>=t
|
33
|
+
[ダメージ計算]を行う。成否と【HP】の減少量を表示する。
|
34
|
+
x: 6面ダイス数
|
35
|
+
t: 防御力
|
36
|
+
・各種表
|
37
|
+
関係決定表 RELA
|
38
|
+
平時天才軍師表 PTGS
|
39
|
+
平時英傑表 PTHE
|
40
|
+
スカウト表 SCOU
|
41
|
+
変調表 BDST
|
42
|
+
MESSAGETEXT
|
43
|
+
|
44
|
+
def initialize(command)
|
45
|
+
super(command)
|
46
|
+
|
47
|
+
@d66_sort_type = D66SortType::ASC
|
48
|
+
@round_type = RoundType::FLOOR
|
49
|
+
end
|
50
|
+
|
51
|
+
register_prefix('TN(6|10)[CSBYA]*', '\d+DM')
|
52
|
+
|
53
|
+
def eval_game_system_specific_command(command)
|
54
|
+
roll_judge(command) || roll_damage(command) || roll_tables(command, self.class::TABLES)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# 行為判定
|
60
|
+
def roll_judge(command)
|
61
|
+
m = /^TN(6|10)([CSBYA]*)$/.match(command)
|
62
|
+
unless m
|
63
|
+
return nil
|
64
|
+
end
|
65
|
+
|
66
|
+
# 成功となる出目
|
67
|
+
success_dices = [4, 5, 6, 7, 8, 9, 10]
|
68
|
+
|
69
|
+
# スペシャルとなる出目
|
70
|
+
special_dices = [6, 10]
|
71
|
+
|
72
|
+
# ファンブルとなる出目
|
73
|
+
fumble_dices = [1]
|
74
|
+
|
75
|
+
# 有利
|
76
|
+
advantage = m[1] == "10"
|
77
|
+
|
78
|
+
# 不調 気づかぬうちの不満
|
79
|
+
complaints = m[2].include?("C")
|
80
|
+
|
81
|
+
# 軍師スキル 〇〇サポート
|
82
|
+
support = m[2].include?("S")
|
83
|
+
|
84
|
+
# 英傑スキル/武人 煌めく刃
|
85
|
+
blade = m[2].include?("B")
|
86
|
+
|
87
|
+
# 英傑スキル/カリスマ 御身のためならば
|
88
|
+
you = m[2].include?("Y")
|
89
|
+
|
90
|
+
# 英傑スキル/英傑汎用 凄腕エージェント
|
91
|
+
agent = m[2].include?("A")
|
92
|
+
|
93
|
+
# 〇〇サポート、煌めく刃、御身のためならば、凄腕エージェントいずれかの適用時
|
94
|
+
if support | blade | you | agent
|
95
|
+
# 成功となる出目に3を追加
|
96
|
+
success_dices.push(3)
|
97
|
+
end
|
98
|
+
|
99
|
+
# 煌めく刃、御身のためならば、凄腕エージェントいずれかの適用時
|
100
|
+
if blade | you | agent
|
101
|
+
# スペシャルとなる出目に3を追加
|
102
|
+
special_dices.push(3)
|
103
|
+
end
|
104
|
+
|
105
|
+
# 気づかぬうちの不満適用時
|
106
|
+
if complaints
|
107
|
+
# 成功となる出目から4を削除
|
108
|
+
success_dices.delete(4)
|
109
|
+
end
|
110
|
+
|
111
|
+
dice_size = advantage ? 10 : 6
|
112
|
+
dice_list = @randomizer.roll_barabara(2, dice_size)
|
113
|
+
|
114
|
+
texts = []
|
115
|
+
is_critical = false
|
116
|
+
is_fumble = false
|
117
|
+
is_success = false
|
118
|
+
|
119
|
+
# スペシャルとなる出目を含む場合
|
120
|
+
unless dice_list.intersection(special_dices).empty?
|
121
|
+
# クリティカルフラグを立てる
|
122
|
+
is_critical = true
|
123
|
+
# スペシャルのシステムメッセージを追加
|
124
|
+
texts.push(translate("TensaiGunshiNiNaro.JUDGE.critical"))
|
125
|
+
special_effects = []
|
126
|
+
# 通常時の追加効果
|
127
|
+
special_effects.push(translate("TensaiGunshiNiNaro.NORMAL.critical"))
|
128
|
+
# 英傑スキル/武人 煌めく刃による追加効果
|
129
|
+
special_effects.push(translate("TensaiGunshiNiNaro.BLADE.critical")) if blade
|
130
|
+
# 英傑スキル/カリスマ 御身のためならばによる追加効果
|
131
|
+
special_effects.push(translate("TensaiGunshiNiNaro.YOU.critical")) if you
|
132
|
+
# 追加効果を結合してカッコ内に格納
|
133
|
+
texts.push("(#{special_effects.join('')})")
|
134
|
+
end
|
135
|
+
|
136
|
+
# ファンブルとなる出目を含む場合
|
137
|
+
unless dice_list.intersection(fumble_dices).empty?
|
138
|
+
# ファンブルフラグを立てる
|
139
|
+
is_fumble = true
|
140
|
+
# ファンブルのシステムメッセージを追加
|
141
|
+
texts.push(translate("TensaiGunshiNiNaro.JUDGE.fumble"))
|
142
|
+
# ファンブルの追加効果をカッコ内に格納
|
143
|
+
texts.push("(#{translate('TensaiGunshiNiNaro.NORMAL.fumble')})")
|
144
|
+
end
|
145
|
+
|
146
|
+
if dice_list.intersection(success_dices).empty?
|
147
|
+
# 成功となる出目を含まない場合
|
148
|
+
# 失敗の汎用メッセージを追加
|
149
|
+
texts.push(translate("failure"))
|
150
|
+
else
|
151
|
+
# 成功となる出目を含む場合
|
152
|
+
# 成功フラグを立てる
|
153
|
+
is_success = true
|
154
|
+
# 成功の汎用メッセージを追加
|
155
|
+
texts.push(translate("success"))
|
156
|
+
end
|
157
|
+
|
158
|
+
return Result.new.tap do |r|
|
159
|
+
# テキストを整形
|
160
|
+
r.text = "#{command} > [#{dice_list.join(',')}] > #{texts.join('')}"
|
161
|
+
# 各種成否を格納
|
162
|
+
r.condition = is_success
|
163
|
+
r.critical = is_critical
|
164
|
+
r.fumble = is_fumble
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# ダメージ計算
|
169
|
+
def roll_damage(command)
|
170
|
+
parser = Command::Parser.new("DM", round_type: @round_type)
|
171
|
+
.has_prefix_number
|
172
|
+
.disable_modifier
|
173
|
+
.restrict_cmp_op_to(:>=)
|
174
|
+
parsed = parser.parse(command)
|
175
|
+
unless parsed
|
176
|
+
return nil
|
177
|
+
end
|
178
|
+
|
179
|
+
text = ''
|
180
|
+
is_success = false
|
181
|
+
|
182
|
+
# ダメージ計算
|
183
|
+
damage = @randomizer.roll_sum(parsed.prefix_number, 6)
|
184
|
+
# HP減少量計算
|
185
|
+
dec = damage / parsed.target_number
|
186
|
+
|
187
|
+
# HP減少量の最大値は3
|
188
|
+
dec = 3 if dec > 3
|
189
|
+
|
190
|
+
if dec > 0
|
191
|
+
# HPを減らせた場合
|
192
|
+
# 成功フラグを立てる
|
193
|
+
is_success = true
|
194
|
+
# 成功メッセージを追加
|
195
|
+
text = translate("TensaiGunshiNiNaro.DAMAGE.success", damage: damage.to_s, dec: dec.to_s)
|
196
|
+
else
|
197
|
+
# 失敗メッセージを追加
|
198
|
+
text = translate("TensaiGunshiNiNaro.DAMAGE.failure", damage: damage.to_s)
|
199
|
+
end
|
200
|
+
|
201
|
+
return Result.new.tap do |r|
|
202
|
+
# テキストを整形
|
203
|
+
r.text = "#{command} > #{damage} > #{text}"
|
204
|
+
# 各種成否を格納
|
205
|
+
r.condition = is_success
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
class << self
|
210
|
+
private
|
211
|
+
|
212
|
+
def translate_tables(locale)
|
213
|
+
{
|
214
|
+
"RELA" => DiceTable::D66Table.from_i18n("TensaiGunshiNiNaro.table.RELA", locale),
|
215
|
+
"PTGS" => DiceTable::D66Table.from_i18n("TensaiGunshiNiNaro.table.PTGS", locale),
|
216
|
+
"PTHE" => DiceTable::D66Table.from_i18n("TensaiGunshiNiNaro.table.PTHE", locale),
|
217
|
+
"SCOU" => DiceTable::D66Table.from_i18n("TensaiGunshiNiNaro.table.SCOU", locale),
|
218
|
+
"BDST" => DiceTable::Table.from_i18n("TensaiGunshiNiNaro.table.BDST", locale),
|
219
|
+
}
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
TABLES = translate_tables(:ja_jp)
|
224
|
+
|
225
|
+
register_prefix(TABLES.keys)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
@@ -0,0 +1,406 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BCDice
|
4
|
+
module GameSystem
|
5
|
+
class TheOneRing2nd < Base
|
6
|
+
# ゲームシステムの識別子
|
7
|
+
ID = "TheOneRing2nd"
|
8
|
+
|
9
|
+
# ゲームシステム名
|
10
|
+
NAME = "一つの指輪:指輪物語TRPG2版"
|
11
|
+
|
12
|
+
# ゲームシステム名の読みがな
|
13
|
+
SORT_KEY = "ひとつのゆひわゆひわものかたりTRPG2"
|
14
|
+
|
15
|
+
HELP_MESSAGE = <<~TEXT
|
16
|
+
・判定コマンド(nRG[x][@y][Az][f[0|1]][i[0|1]][w[0|1]][m[0|1]])
|
17
|
+
判定用に難易度nを指定して判定ダイスを振る。技量ダイスx、痛打判定値y、修正値zを指定可能。
|
18
|
+
技量ダイス、痛打判定値、修正値は0、または未指定(0と同じ)にできる。
|
19
|
+
痛打判定値の0、未指定は痛打判定を行わない。
|
20
|
+
修正値は判定合計値に加算され、「ガンダルフ・ルーン」や「サウロンの目」はその影響を受けない。
|
21
|
+
例1: 13RG (難易度13 技量ダイス0個)
|
22
|
+
例2: 13RG3 (難易度13 技量ダイス3個)
|
23
|
+
例3: 13RG3@10A1 (難易度13 技量ダイス3個、痛打判定10、結果に1を加算)
|
24
|
+
|
25
|
+
・表用コマンド(FD[x][f[0|1]][i[0|1]])
|
26
|
+
表用に判定ダイスを振る。修正値xが指定可能。修正値は0、あるいは未指定(0と同じ)にできる。
|
27
|
+
「ガンダルフ・ルーン」や「サウロンの目」は修正値の影響を受けず、値が10を越えることもない。
|
28
|
+
例1: FD (1d12で判定)
|
29
|
+
例2: FD1 (1d12で判定し、ダイス目に+1修正)
|
30
|
+
|
31
|
+
・コマンドオプション
|
32
|
+
オプションは、判定コマンドなら4個まで、表用コマンドなら2個まで、順不同で指定可能(重複可)。
|
33
|
+
f: 有利(favoured)オプション。不利と同時指定時は相殺。選択された値に◎。
|
34
|
+
i: 不利(ill-favoured)オプション。有利と同時指定時は相殺。選択された値に◎。
|
35
|
+
例1: 13RG3f (難易度13 技量ダイス3個、有利)
|
36
|
+
例2: FD1f (1修正、有利)
|
37
|
+
例3: 13RG3if (難易度13 技量ダイス3個、不利、有利)
|
38
|
+
※有利/不利は相殺。
|
39
|
+
|
40
|
+
判定コマンドでは更に下記のオプションを同じ条件で指定可能。
|
41
|
+
w: 疲労(weary)状態オプション。
|
42
|
+
m: 絶望(miserable)状態オプション。
|
43
|
+
例1: 13RG3wf (難易度13 技量ダイス3個、疲労状態、有利)
|
44
|
+
例2: 13RG3fiwm (難易度13 技量ダイス3個、有利、不利、疲労状態、絶望状態)
|
45
|
+
※有利/不利は相殺。最大オプション数である4つを指定。
|
46
|
+
|
47
|
+
・オプションスイッチ
|
48
|
+
指定したオプションのon/offを1/0で指定可能。1はon、0はoffを表す。
|
49
|
+
複数の同じオプションへのスイッチ指定は、最後のスイッチが有効となる。
|
50
|
+
例1: 13RG3if0 (難易度13 技量ダイス3個、不利はon、有利はoff)
|
51
|
+
※ 有利指定がoffのため、相殺されず不利となる。
|
52
|
+
例2: 13RG3f1f0 (難易度13 技量ダイス3個、有利は最終的にoff)
|
53
|
+
TEXT
|
54
|
+
|
55
|
+
register_prefix('\d+RG', 'FD')
|
56
|
+
|
57
|
+
SAURONS_EYE_NUMBER = 11 # サウロンの目
|
58
|
+
GANDALF_RUNE_NUMBER = 12 # ガンダルフ・ルーン
|
59
|
+
|
60
|
+
CHOICE_DIE_MARK = '◎' # 有利/不利の状態で選択されたダイスにつけるマーク
|
61
|
+
|
62
|
+
# 有利/不利状態のenum
|
63
|
+
module FavouredState
|
64
|
+
NORMAL = -98 # 通常状態
|
65
|
+
FAVOURED = -99 # 有利状態
|
66
|
+
ILLFAVOURED = -100 # 不利状態
|
67
|
+
end
|
68
|
+
|
69
|
+
def eval_game_system_specific_command(command)
|
70
|
+
case command
|
71
|
+
when /^\d+RG/i
|
72
|
+
return rg_command_exec(command)
|
73
|
+
when /^FD/i
|
74
|
+
return fd_command_exec(command)
|
75
|
+
end
|
76
|
+
return "Error" # 到達しないはずだが、念のため
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# ================ RG/FGコマンド共有メソッド等 ================#
|
82
|
+
|
83
|
+
# オプションデータクラス
|
84
|
+
class OptionData
|
85
|
+
attr_reader :favoured_state, :weary, :miserable
|
86
|
+
|
87
|
+
def initialize(favoured_state_value: FavouredState::NORMAL, weary_condition: false, miserable_condition: false)
|
88
|
+
@favoured_state = favoured_state_value
|
89
|
+
@weary = weary_condition
|
90
|
+
@miserable = miserable_condition
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# 指定された修正値文字列を取得
|
95
|
+
def get_adjust_number_text(adjust_number)
|
96
|
+
adjust_number_text = ""
|
97
|
+
|
98
|
+
if adjust_number > 0
|
99
|
+
adjust_number_text = "+#{adjust_number}"
|
100
|
+
elsif adjust_number < 0
|
101
|
+
adjust_number_text = adjust_number.to_s
|
102
|
+
end
|
103
|
+
|
104
|
+
return adjust_number_text
|
105
|
+
end
|
106
|
+
|
107
|
+
# 指定された状態文字列を取得
|
108
|
+
def get_condition_text(opts)
|
109
|
+
if opts.favoured_state == FavouredState::NORMAL && !opts.weary && !opts.miserable
|
110
|
+
return ""
|
111
|
+
end
|
112
|
+
|
113
|
+
condition_text = "\n状態:"
|
114
|
+
if opts.favoured_state == FavouredState::FAVOURED
|
115
|
+
condition_text = "#{condition_text}有利 "
|
116
|
+
elsif opts.favoured_state == FavouredState::ILLFAVOURED
|
117
|
+
condition_text = "#{condition_text}不利 "
|
118
|
+
end
|
119
|
+
if opts.weary
|
120
|
+
condition_text = "#{condition_text}疲労 "
|
121
|
+
end
|
122
|
+
if opts.miserable
|
123
|
+
condition_text = "#{condition_text}絶望 "
|
124
|
+
end
|
125
|
+
|
126
|
+
return condition_text.rstrip
|
127
|
+
end
|
128
|
+
|
129
|
+
# 指定された状態文字列を取得
|
130
|
+
def get_options(opt_params)
|
131
|
+
favoured_state_value = FavouredState::NORMAL
|
132
|
+
miserable_condition = false
|
133
|
+
weary_condition = false
|
134
|
+
|
135
|
+
opt_params.each do |x|
|
136
|
+
case x[/[WFIM]/]
|
137
|
+
when "W"
|
138
|
+
weary_condition = on_option_switch?(x)
|
139
|
+
when "F"
|
140
|
+
favoured_state_value = get_favoured_state(on_option_switch?(x), favoured_state_value, FavouredState::FAVOURED)
|
141
|
+
when "I"
|
142
|
+
favoured_state_value = get_favoured_state(on_option_switch?(x), favoured_state_value, FavouredState::ILLFAVOURED)
|
143
|
+
when "M"
|
144
|
+
miserable_condition = on_option_switch?(x)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
return OptionData.new(favoured_state_value: favoured_state_value, weary_condition: weary_condition, miserable_condition: miserable_condition)
|
149
|
+
end
|
150
|
+
|
151
|
+
# オプションから有利/不利状態指定を取得
|
152
|
+
def get_favoured_state(option_switch, before_favoured_state_value, tagert_state_type)
|
153
|
+
if option_switch
|
154
|
+
if before_favoured_state_value == tagert_state_type || before_favoured_state_value == FavouredState::NORMAL
|
155
|
+
return tagert_state_type
|
156
|
+
end
|
157
|
+
|
158
|
+
return FavouredState::NORMAL
|
159
|
+
else
|
160
|
+
if before_favoured_state_value == tagert_state_type
|
161
|
+
return FavouredState::NORMAL
|
162
|
+
end
|
163
|
+
end
|
164
|
+
return before_favoured_state_value
|
165
|
+
end
|
166
|
+
|
167
|
+
# オプションのON/OFFを取得
|
168
|
+
def on_option_switch?(opt_value)
|
169
|
+
if opt_value.length == 1 || opt_value[1..opt_value.length].to_i > 0
|
170
|
+
return true
|
171
|
+
end
|
172
|
+
|
173
|
+
return false
|
174
|
+
end
|
175
|
+
|
176
|
+
# 技量ダイスロールを行う
|
177
|
+
def make_successdice_roll(success_dice_count, weary_condition)
|
178
|
+
dice_list = @randomizer.roll_barabara(success_dice_count, 6)
|
179
|
+
success_count = dice_list.count(6)
|
180
|
+
if weary_condition
|
181
|
+
success_total_number = dice_list.reject { |i| i <= 3 }.sum
|
182
|
+
else
|
183
|
+
success_total_number = dice_list.sum
|
184
|
+
end
|
185
|
+
return dice_list.to_s, success_total_number, success_count
|
186
|
+
end
|
187
|
+
|
188
|
+
# 判定ダイスロールを行う
|
189
|
+
def make_featdice_roll(favoured_state_value)
|
190
|
+
feat_dice_count = favoured_state_value == FavouredState::NORMAL ? 1 : 2
|
191
|
+
dice_list = @randomizer.roll_barabara(feat_dice_count, 12)
|
192
|
+
|
193
|
+
choice_die_number = die_choice(dice_list, favoured_state_value)
|
194
|
+
if feat_dice_count > 1
|
195
|
+
|
196
|
+
choice_index = dice_list.find_index(choice_die_number)
|
197
|
+
|
198
|
+
first_die = "#{CHOICE_DIE_MARK if choice_index == 0}#{get_specal_die_str(dice_list[0])}"
|
199
|
+
second_die = "#{CHOICE_DIE_MARK if choice_index == 1}#{get_specal_die_str(dice_list[1])}"
|
200
|
+
|
201
|
+
feat_result_text = "[#{first_die}, #{second_die}]"
|
202
|
+
else
|
203
|
+
feat_result_text = "[#{get_specal_die_str(choice_die_number)}]"
|
204
|
+
end
|
205
|
+
|
206
|
+
return feat_result_text, choice_die_number, feat_dice_count
|
207
|
+
end
|
208
|
+
|
209
|
+
# 有利/不利を含めて判定ダイスの結果を取得
|
210
|
+
def die_choice(dice_list, favoured_state_value)
|
211
|
+
if favoured_state_value == FavouredState::ILLFAVOURED
|
212
|
+
if dice_list.count(SAURONS_EYE_NUMBER) >= 1
|
213
|
+
return SAURONS_EYE_NUMBER
|
214
|
+
else
|
215
|
+
return dice_list.min
|
216
|
+
end
|
217
|
+
elsif favoured_state_value == FavouredState::FAVOURED
|
218
|
+
if dice_list.count(GANDALF_RUNE_NUMBER) >= 1
|
219
|
+
return GANDALF_RUNE_NUMBER
|
220
|
+
else
|
221
|
+
# ガンダルフ・ルーンが無ければサウロンの目を除いた最大値を選ぶ
|
222
|
+
# ※ どちらもサウロンの目ならサウロンの目を返す
|
223
|
+
return dice_list.count(SAURONS_EYE_NUMBER) == 2 ? SAURONS_EYE_NUMBER : dice_list.reject { |x| x == SAURONS_EYE_NUMBER }.max
|
224
|
+
end
|
225
|
+
end
|
226
|
+
return dice_list[0]
|
227
|
+
end
|
228
|
+
|
229
|
+
# 判定ダイスが特殊ダイス目だった場合、該当文字列に変換する
|
230
|
+
def get_specal_die_str(die_number)
|
231
|
+
if die_number == GANDALF_RUNE_NUMBER
|
232
|
+
return "ガンダルフ・ルーン"
|
233
|
+
elsif die_number == SAURONS_EYE_NUMBER
|
234
|
+
return "サウロンの目"
|
235
|
+
end
|
236
|
+
|
237
|
+
return die_number
|
238
|
+
end
|
239
|
+
|
240
|
+
# ================ FDコマンド ================#
|
241
|
+
|
242
|
+
FD_ADJUST_NUMBER_INDEX = 2
|
243
|
+
FD_OPTION_START_INDEX = 3
|
244
|
+
|
245
|
+
# FDコマンド実行
|
246
|
+
def fd_command_exec(command)
|
247
|
+
m = /\A(FD)(-?\d*)?([FI]-?\d*)?([FI]-?\d*)?$/.match(command)
|
248
|
+
unless m
|
249
|
+
return ''
|
250
|
+
end
|
251
|
+
|
252
|
+
# コマンドパラメータ取得
|
253
|
+
adjust_number, opts = get_fd_params(m)
|
254
|
+
|
255
|
+
# 判定ダイス処理
|
256
|
+
feat_result_text, feat_die_number, feat_dice_count = make_featdice_roll(opts.favoured_state)
|
257
|
+
result_header_text = "(#{feat_dice_count}D12"
|
258
|
+
|
259
|
+
return get_fd_roll_result(result_header_text, feat_result_text, feat_die_number, feat_dice_count, adjust_number)
|
260
|
+
end
|
261
|
+
|
262
|
+
# FDコマンド判定結果の取得
|
263
|
+
def get_fd_roll_result(result_header_text, feat_result_text, feat_die_number, feat_dice_count, adjust_number)
|
264
|
+
# 修正値処理
|
265
|
+
reslt_die_number, adjust_number_text = get_fd_adjust(feat_die_number, adjust_number)
|
266
|
+
|
267
|
+
result_header_text = "#{result_header_text}#{adjust_number_text}) > #{feat_result_text}#{adjust_number_text}"
|
268
|
+
if adjust_number != 0 || feat_dice_count != 1
|
269
|
+
return "#{result_header_text} > [#{get_specal_die_str(reslt_die_number)}]"
|
270
|
+
end
|
271
|
+
|
272
|
+
return result_header_text
|
273
|
+
end
|
274
|
+
|
275
|
+
# FDコマンドの修正値取得
|
276
|
+
def get_fd_adjust(feat_die_number, adjust_number)
|
277
|
+
if [SAURONS_EYE_NUMBER, GANDALF_RUNE_NUMBER].include?(feat_die_number)
|
278
|
+
return feat_die_number, get_adjust_number_text(adjust_number)
|
279
|
+
end
|
280
|
+
|
281
|
+
res_total_num = feat_die_number + adjust_number
|
282
|
+
if res_total_num > 10
|
283
|
+
res_total_num = 10
|
284
|
+
elsif res_total_num < 1
|
285
|
+
res_total_num = 1
|
286
|
+
end
|
287
|
+
return res_total_num, get_adjust_number_text(adjust_number)
|
288
|
+
end
|
289
|
+
|
290
|
+
# FDコマンドパラメータの取得
|
291
|
+
def get_fd_params(m)
|
292
|
+
adjust_number = m[FD_ADJUST_NUMBER_INDEX].to_i
|
293
|
+
|
294
|
+
opt_params = m[FD_OPTION_START_INDEX..m.length].compact
|
295
|
+
|
296
|
+
return adjust_number, get_options(opt_params)
|
297
|
+
end
|
298
|
+
|
299
|
+
# ================ RGコマンド ================#
|
300
|
+
|
301
|
+
RG_DIFFICULTY_INDEX = 1
|
302
|
+
RG_SUCCESS_DICE_INDEX = 3
|
303
|
+
RG_PIERCING_BLOWS_INDEX = 5
|
304
|
+
RG_ADJUST_NUMBER_INDEX = 7
|
305
|
+
RG_OPTION_START_INDEX = 8
|
306
|
+
|
307
|
+
# RGコマンド実行
|
308
|
+
def rg_command_exec(command)
|
309
|
+
m = /\A(\d+)(RG)(\d*)(@(\d{0,2}))?(A(-?\d*))?([WFIM]-?\d*)?([WFIM]-?\d*)?([WFIM]-?\d*)?([WFIM]-?\d*)?$/.match(command)
|
310
|
+
unless m
|
311
|
+
return ''
|
312
|
+
end
|
313
|
+
|
314
|
+
success_count = 0
|
315
|
+
|
316
|
+
# コマンドパラメータ取得
|
317
|
+
difficulty, success_dice_count, piercing_blows_number, adjust_number, opts = get_rg_params(m)
|
318
|
+
|
319
|
+
# 判定ダイス処理
|
320
|
+
feat_result_text, feat_die_number, feat_dice_count = make_featdice_roll(opts.favoured_state)
|
321
|
+
total_dice_number = (feat_die_number != SAURONS_EYE_NUMBER ? feat_die_number : 0)
|
322
|
+
|
323
|
+
result_header_text = "(#{feat_dice_count}D12"
|
324
|
+
result_dice_text = feat_result_text
|
325
|
+
|
326
|
+
# 技量ダイスが指定されているならその処理
|
327
|
+
if success_dice_count > 0
|
328
|
+
success_result_text, success_total_number, success_count = make_successdice_roll(success_dice_count, opts.weary)
|
329
|
+
total_dice_number += success_total_number
|
330
|
+
|
331
|
+
result_header_text = "#{result_header_text}+#{success_dice_count}D6"
|
332
|
+
result_dice_text = "#{result_dice_text}+#{success_result_text}"
|
333
|
+
end
|
334
|
+
|
335
|
+
# 修正値処理
|
336
|
+
total_dice_number, adjust_number_text = get_rg_adjust(total_dice_number, adjust_number)
|
337
|
+
|
338
|
+
result_header_text = "#{result_header_text}#{adjust_number_text}) > #{result_dice_text}#{adjust_number_text}"
|
339
|
+
|
340
|
+
return get_rg_roll_result(result_header_text, difficulty, feat_die_number, piercing_blows_number, total_dice_number, success_count, opts)
|
341
|
+
end
|
342
|
+
|
343
|
+
# 修正値と修正値テキストの取得
|
344
|
+
def get_rg_adjust(total_dice_number, adjust_number)
|
345
|
+
total_dice_number += adjust_number
|
346
|
+
total_dice_number = 0 if total_dice_number < 0
|
347
|
+
|
348
|
+
return total_dice_number, get_adjust_number_text(adjust_number)
|
349
|
+
end
|
350
|
+
|
351
|
+
# RGコマンド判定結果の取得
|
352
|
+
def get_rg_roll_result(result_header_text, difficulty, feat_die_number, piercing_blows_number, total_dice_number, success_count, opts)
|
353
|
+
# 状態表示取得
|
354
|
+
condition_text = get_condition_text(opts)
|
355
|
+
|
356
|
+
success_count_text = "成功度 #{success_count}"
|
357
|
+
|
358
|
+
# 痛打判定をブロック化
|
359
|
+
piercing_blows = lambda() { |feat_die_num, piercing_blows_num, res_text, cond_text|
|
360
|
+
if piercing_blows_num > 0 && feat_die_num >= piercing_blows_num && feat_die_num != SAURONS_EYE_NUMBER
|
361
|
+
res_text = "#{res_text} 痛打発生!"
|
362
|
+
end
|
363
|
+
return "#{res_text}#{cond_text}"
|
364
|
+
}
|
365
|
+
|
366
|
+
if feat_die_number == GANDALF_RUNE_NUMBER
|
367
|
+
gandalf_rune_text = "#{result_header_text}:自動成功[#{success_count_text}]"
|
368
|
+
gandalf_rune_text = piercing_blows.call(feat_die_number, piercing_blows_number, gandalf_rune_text, condition_text)
|
369
|
+
if success_count >= 2
|
370
|
+
return Result.critical(gandalf_rune_text)
|
371
|
+
end
|
372
|
+
|
373
|
+
return Result.success(gandalf_rune_text)
|
374
|
+
elsif opts.miserable && feat_die_number == SAURONS_EYE_NUMBER
|
375
|
+
return Result.failure("#{result_header_text}:自動失敗#{condition_text}")
|
376
|
+
end
|
377
|
+
|
378
|
+
result_detail_text = "難易度 #{difficulty} 達成値 #{total_dice_number}"
|
379
|
+
if difficulty > total_dice_number
|
380
|
+
return Result.failure("#{result_header_text} #{result_detail_text}:失敗#{condition_text}")
|
381
|
+
end
|
382
|
+
|
383
|
+
success_text = "#{result_header_text} #{result_detail_text}:成功[#{success_count_text}]"
|
384
|
+
success_text = piercing_blows.call(feat_die_number, piercing_blows_number, success_text, condition_text)
|
385
|
+
if success_count >= 2
|
386
|
+
return Result.critical(success_text)
|
387
|
+
end
|
388
|
+
|
389
|
+
return Result.success(success_text)
|
390
|
+
end
|
391
|
+
|
392
|
+
# RGコマンドパラメータの取得
|
393
|
+
def get_rg_params(m)
|
394
|
+
difficulty = m[RG_DIFFICULTY_INDEX].to_i
|
395
|
+
|
396
|
+
success_dice_count = m[RG_SUCCESS_DICE_INDEX].to_i
|
397
|
+
adjust_number = m[RG_ADJUST_NUMBER_INDEX].to_i
|
398
|
+
piercing_blows_number = m[RG_PIERCING_BLOWS_INDEX]&.to_i || -1 # -1は痛打判定自体を行わない
|
399
|
+
|
400
|
+
opt_params = m[RG_OPTION_START_INDEX..m.length].compact
|
401
|
+
|
402
|
+
return difficulty, success_dice_count, piercing_blows_number, adjust_number, get_options(opt_params)
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|