bcdice 3.11.0 → 3.12.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.
@@ -96,7 +96,7 @@ module BCDice
96
96
  "大漁\n船内マップ上にいるすべてのキャラクターの【生命点】の最大値を「2点」増加する。この効果は重複しない。\n 飛翔イカの群れだ! どうも、 窓から漏れる明かりにつられてやってきたらしい。網をはろう。今夜は新鮮なイカがたらふく食べられそうだ。",
97
97
  "気流+1\n飛空艇コマを1スポット分進める。\n 他の空域よりも、比較的強い流れが一定の方向に吹き続けている空域。ときに探空士たちの手助けになり、ときに探空士たちに立ちはだかる。どの空域にどんな風が流れているかを見極めて進むのが、空の旅での基本だ。",
98
98
  "ケセランパセラン\nキミは任意の船内マップ上に配置されてるパーツ1つを選択する。そのパーツが【快適度】のキーワード効果がある場合、このセッションの間、その数値は「1点」高いものとして扱う。\n ふわふわとした大きな綿毛のような浮遊生物。その毛のさわり心地は、上級階級のソファにも使われるほど柔らかい。捕まえて飼うことができれば、一服の癒やしをあたえてくれることだろう。",
99
- "うさこぷたー\nキミの【生命点】を「3点」回復する。\n ふわふわとした大きな綿毛のような浮遊生物。その毛のさわり心地は、上流階級のソファにも使われるほど柔らかい。 捕まえて飼うことができれば、一服の癒やしをあたえてくれることだろう。"
99
+ "うさこぷたー\nキミの【生命点】を「3点」回復する。\n ふたつの耳を回転させて空を飛ぶうさぎのような浮遊生物が、ずっとこちらを見つめている。かわいいはかわいいのだが、こいつは一体なんなんだろう……。"
100
100
  ]
101
101
  ),
102
102
  "NEO" => DiceTable::Table.new(
@@ -334,6 +334,11 @@ module BCDice
334
334
  if command.modifier_after_half != 0
335
335
  text += Format.modifier(command.modifier_after_half)
336
336
  end
337
+ elsif command.one_and_a_half
338
+ text = "(#{text})*1.5"
339
+ if command.modifier_after_one_and_a_half != 0
340
+ text += Format.modifier(command.modifier_after_one_and_a_half)
341
+ end
337
342
  end
338
343
  sequence.push(text)
339
344
  elsif command.half
@@ -342,6 +347,12 @@ module BCDice
342
347
  text += Format.modifier(command.modifier_after_half)
343
348
  end
344
349
  sequence.push(text)
350
+ elsif command.one_and_a_half
351
+ text = "#{rateResults.first}*1.5"
352
+ if command.modifier_after_one_and_a_half != 0
353
+ text += Format.modifier(command.modifier_after_one_and_a_half)
354
+ end
355
+ sequence.push(text)
345
356
  end
346
357
 
347
358
  if round > 1
@@ -355,6 +366,11 @@ module BCDice
355
366
  if command.modifier_after_half != 0
356
367
  total += command.modifier_after_half
357
368
  end
369
+ elsif command.one_and_a_half
370
+ total = (total * 1.5).ceil
371
+ if command.modifier_after_one_and_a_half != 0
372
+ total += command.modifier_after_one_and_a_half
373
+ end
358
374
  end
359
375
 
360
376
  total_text = total.to_s
@@ -39,6 +39,13 @@ module BCDice
39
39
   クリティカル値を指定しない場合、クリティカルなしと扱われます。
40
40
   例)HK20  K20h  HK10-5@9  K10-5@9H  K20gfH  K20+8H+2  K20+8H+(1+1)
41
41
 
42
+ ・レーティング表の1.5倍 (OHKx, KxOH+N)
43
+  レーティング表の先頭または末尾に"OH"をつけると、レーティング表を振って最終結果を1.5倍します。
44
+  末尾につけた場合、直後に修正ををつけることで、1.5倍後の加減算を行うことができます。
45
+  この際、複数の項による修正にはカッコで囲うことが必要です(カッコがないとパースに失敗します)
46
+  クリティカル値を指定しない場合、クリティカルなしと扱われます。
47
+  例)OHK20  K20oh  OHK10-5@9  K20+8OH+2  K20+8OH+(1+1)
48
+
42
49
  ・ダイス目の修正(運命変転やクリティカルレイ用)
43
50
   末尾に「$修正値」でダイス目に修正がかかります。
44
51
   $+1と修正表記ならダイス目に+修正、$9のように固定値ならダイス目をその出目に差し替え。
@@ -82,7 +89,7 @@ module BCDice
82
89
   アビスカース表を出すことができます。
83
90
  INFO_MESSAGE_TEXT
84
91
 
85
- register_prefix('H?K', 'Gr', '2D6?@\d+', 'FT', 'TT', 'Dru', 'ABT')
92
+ register_prefix('H?K', 'OHK', 'Gr', '2D6?@\d+', 'FT', 'TT', 'Dru', 'ABT')
86
93
 
87
94
  def eval_game_system_specific_command(command)
88
95
  case command
@@ -22,14 +22,14 @@ module BCDice
22
22
  2VMF6+3
23
23
  2VMI9H3
24
24
 
25
- 難易度指定:成功数のカウント、判定成功と失敗、Critical処理、Critical Winのチェックを行う
25
+ 難易度指定:成功数のカウント、判定成功と失敗、Critical処理、Critical Win、Total Failureのチェックを行う
26
26
  (Hungerダイスがある場合)Messy CriticalとBestial Failureチェックを行う
27
27
  例) (難易度)VMF(通常ダイス)+(Hungerダイス)
28
28
  (難易度)VMF(通常ダイス)
29
29
  (難易度)VMI(通常ダイス)H(Hungerダイス)
30
30
  (難易度)VMI(通常ダイス)
31
31
 
32
- 難易度省略:成功数のカウント、判定失敗、Critical処理、(Hungerダイスがある場合)Bestial Failureチェックを行う
32
+ 難易度省略:成功数のカウント、判定失敗、Critical処理、Total Failure、(Hungerダイスがある場合)Bestial Failureチェックを行う
33
33
  判定成功、Messy Criticalのチェックを行わない
34
34
  Critical Win、(Hungerダイスがある場合)Bestial Failure、Messy Criticalのヒントを出力
35
35
  例) VMF(通常ダイス)+(Hungerダイス)
@@ -58,7 +58,7 @@ module BCDice
58
58
  register_prefix('\d*(VMF|(VMI\d*(H\d?)?))')
59
59
 
60
60
  def eval_game_system_specific_command(command)
61
- m = /\A(\d+)?(((VMF)(\d)(\+(\d+))?)|((VMI)(\d)(H(\d+))?))$/.match(command)
61
+ m = /\A(\d+)?(((VMF)(\d+)(\+(\d+))?)|((VMI)(\d+)(H(\d+))?))$/.match(command)
62
62
  unless m
63
63
  return ''
64
64
  end
@@ -67,6 +67,9 @@ module BCDice
67
67
  if dice_pool < 0
68
68
  return "ダイスプールより多いHungerダイスは指定できません。"
69
69
  end
70
+ if hunger_dice_pool && hunger_dice_pool > 5
71
+ return "Hungerダイス指定は5ダイスが最大です。"
72
+ end
70
73
 
71
74
  dice_text, success_dice, ten_dice, = make_dice_roll(dice_pool)
72
75
  result_text = "(#{dice_pool}D10"
@@ -128,6 +131,9 @@ module BCDice
128
131
  if hunger_botch_dice > 0
129
132
  return Result.fumble("#{result_text}:判定失敗! [Bestial Failure]")
130
133
  end
134
+ if success_dice == 0
135
+ return Result.fumble("#{result_text}:判定失敗! [Total Failure]")
136
+ end
131
137
 
132
138
  return Result.failure("#{result_text}:判定失敗!")
133
139
  end
@@ -137,7 +143,7 @@ module BCDice
137
143
  return Result.fumble("#{result_text}:判定失敗! [Bestial Failure]")
138
144
  end
139
145
 
140
- return Result.failure("#{result_text}:判定失敗!")
146
+ return Result.fumble("#{result_text}:判定失敗! [Total Failure]")
141
147
  else
142
148
  if hunger_botch_dice > 0
143
149
  result_text = "#{result_text}\n 判定失敗なら [Bestial Failure]"
@@ -0,0 +1,173 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class WerewolfTheApocalypse5th < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'WerewolfTheApocalypse5th'
8
+
9
+ # ゲームシステム名
10
+ NAME = 'Werewolf: The Apocalypse 5th Edition'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'わあうふるしあほかりふす5'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~MESSAGETEXT
17
+ ・判定コマンド(nWAFx+x または nWAIxRx)
18
+ WAFコマンドはRageダイスとダイスプールを個別に指定する。
19
+ WAIコマンドはRageダイスをダイスプールの内数として指定する。
20
+
21
+ 例:難易度2、9ダイスプールでRageダイス3個の場合、それぞれ以下のようなコマンドとなる。
22
+ 2WAF6+3
23
+ 2WAI9R3
24
+
25
+ 難易度指定:成功数のカウント、判定成功と失敗、(Rageダイスがある場合)Brutal outcome、Critical処理、Total Failure、Critical Winのチェックを行う
26
+ 例) (難易度)WAF(通常ダイス)+(Rageダイス)
27
+ (難易度)WAF(通常ダイス)
28
+ (難易度)WAI(通常ダイス)R(Rageダイス)
29
+ (難易度)WAI(通常ダイス)
30
+
31
+ 難易度省略:成功数のカウント、判定失敗、(Rageダイスがある場合)Brutal outcome、Critical処理、Total Failureのチェックを行う
32
+ 判定成功チェックを行わない
33
+ Critical Winのヒントを出力
34
+ 例) WAF(通常ダイス)+(Rageダイス)
35
+ WAF(通常ダイス)
36
+ WAI(通常ダイス)R(Rageダイス)
37
+ WAI(通常ダイス)
38
+
39
+ 難易度0指定:Critical処理と成功数のカウントを行い、全てのチェックを行わない
40
+ 例) 0WAF(通常ダイス)+(Rageダイス)
41
+ 0WAF(通常ダイス)
42
+ 0WAI(通常ダイス)+(Rageダイス)
43
+ 0WAI(通常ダイス)
44
+
45
+ MESSAGETEXT
46
+
47
+ DIFFICULTY_INDEX = 1
48
+ DICE_POOL_RAGE_DICE_NO_INCLUDED_INDEX = 5
49
+ RAGE_DICE_NO_INCLUDED_INDEX = 7
50
+ COMMAND_RAGE_DICE_INCLUDED_INDEX = 9
51
+ DICE_POOL_RAGE_DICE_INCLUDED_INDEX = 10
52
+ RAGE_DICE_INCLUDED_INDEX = 12
53
+
54
+ # 難易度に指定可能な特殊値
55
+ NOT_CHECK_SUCCESS = -1 # 判定成功にかかわるチェックを行わない(判定失敗に関わるチェックは行う)
56
+
57
+ register_prefix('\d*(WAF|(WAI\d*(R\d?)?))')
58
+
59
+ def eval_game_system_specific_command(command)
60
+ m = /\A(\d+)?(((WAF)(\d+)(\+(\d+))?)|((WAI)(\d+)(R(\d+))?))$/.match(command)
61
+ unless m
62
+ return ''
63
+ end
64
+
65
+ dice_pool, rage_dice_pool = get_dice_pools(m)
66
+ if dice_pool < 0
67
+ return "ダイスプールより多いRageダイス指定はできません。"
68
+ end
69
+ if rage_dice_pool && rage_dice_pool > 5
70
+ return "5を超えるRageダイス指定はできません。"
71
+ end
72
+
73
+ dice_text, success_dice, ten_dice, = make_dice_roll(dice_pool)
74
+ result_text = "(#{dice_pool}D10"
75
+
76
+ if rage_dice_pool
77
+ rage_dice_text, rage_success_dice, rage_ten_dice, brutal_result_dice = make_dice_roll(rage_dice_pool)
78
+
79
+ brutal_outcome = brutal_result_dice / 2
80
+ ten_dice += rage_ten_dice
81
+ success_dice += rage_success_dice
82
+
83
+ result_text = "#{result_text}+#{rage_dice_pool}D10) > [#{dice_text}]+[#{rage_dice_text}] "
84
+ else
85
+ rage_ten_dice = 0
86
+ brutal_outcome = 0
87
+ result_text = "#{result_text}) > [#{dice_text}] "
88
+ end
89
+
90
+ success_dice += get_critical_success(ten_dice)
91
+
92
+ difficulty = m[DIFFICULTY_INDEX] ? m[DIFFICULTY_INDEX].to_i : NOT_CHECK_SUCCESS
93
+
94
+ return get_roll_result(result_text, success_dice, ten_dice, rage_ten_dice, brutal_outcome, difficulty)
95
+ end
96
+
97
+ private
98
+
99
+ def get_dice_pools(m)
100
+ rage_dice_included_command = m[COMMAND_RAGE_DICE_INCLUDED_INDEX]
101
+ if rage_dice_included_command && rage_dice_included_command == "WAI"
102
+ # Rage Diceを内数処理するの場合
103
+ rage_dice_pool = m[RAGE_DICE_INCLUDED_INDEX]&.to_i
104
+ dice_pool = m[DICE_POOL_RAGE_DICE_INCLUDED_INDEX].to_i - (rage_dice_pool || 0)
105
+ else
106
+ # Rage DiceがPLによる内数指定の場合
107
+ rage_dice_pool = m[RAGE_DICE_NO_INCLUDED_INDEX]&.to_i
108
+ dice_pool = m[DICE_POOL_RAGE_DICE_NO_INCLUDED_INDEX].to_i
109
+ end
110
+ return dice_pool, rage_dice_pool
111
+ end
112
+
113
+ def get_roll_result(result_text, success_dice, ten_dice, _rage_ten_dice, brutal_outcome, difficulty)
114
+ is_critical = ten_dice >= 2
115
+
116
+ if brutal_outcome > 0 && difficulty != 0
117
+ success_dice += 4
118
+ result_text = "#{result_text} [Brutal outcome] 自動失敗、または 成功数=#{success_dice}"
119
+ else
120
+ result_text = "#{result_text} 成功数=#{success_dice}"
121
+ end
122
+
123
+ if difficulty > 0
124
+ result_text = "#{result_text} 難易度=#{difficulty}"
125
+ if success_dice >= difficulty
126
+ result_text = "#{result_text} 差分=#{success_dice - difficulty}"
127
+
128
+ if is_critical
129
+ result_data = Result.critical("#{result_text}:判定成功! [Critical Win]")
130
+ return brutal_outcome > 0 ? result_data.text : result_data
131
+ end
132
+ result_data = Result.success("#{result_text}:判定成功!")
133
+ return brutal_outcome > 0 ? result_data.text : result_data
134
+ else
135
+ if success_dice == 0
136
+ return Result.fumble("#{result_text}:判定失敗! [Total Failure]")
137
+ else
138
+ return Result.failure("#{result_text}:判定失敗!")
139
+ end
140
+ end
141
+ elsif difficulty < 0
142
+ if success_dice == 0
143
+ return Result.fumble("#{result_text}:判定失敗! [Total Failure]")
144
+ else
145
+ if is_critical
146
+ result_text = "#{result_text}\n 判定成功なら [Critical Win]"
147
+ end
148
+ return result_text.to_s
149
+ end
150
+ end
151
+
152
+ # 難易度0指定(=全ての判定チェックを行わない)
153
+ return result_text.to_s
154
+ end
155
+
156
+ def get_critical_success(ten_dice)
157
+ # 10の目が2個毎に追加2成功
158
+ return ((ten_dice / 2) * 2)
159
+ end
160
+
161
+ def make_dice_roll(dice_pool)
162
+ dice_list = @randomizer.roll_barabara(dice_pool, 10)
163
+
164
+ dice_text = dice_list.join(',')
165
+ success_dice = dice_list.count { |x| x >= 6 }
166
+ ten_dice = dice_list.count(10)
167
+ brutal_result_dice = dice_list.count(1) + dice_list.count(2)
168
+
169
+ return dice_text, success_dice, ten_dice, brutal_result_dice
170
+ end
171
+ end
172
+ end
173
+ end
@@ -34,6 +34,9 @@ module BCDice
34
34
  # @return [Integer, nil]
35
35
  attr_accessor :modifier_after_half
36
36
 
37
+ # @return [Integer, nil]
38
+ attr_accessor :modifier_after_one_and_a_half
39
+
37
40
  def settable_first_roll_adjust_option?
38
41
  return first_modify.nil? && first_to.nil?
39
42
  end
@@ -37,6 +37,9 @@ module BCDice
37
37
  # @return [Integer, nil]
38
38
  attr_accessor :modifier_after_half
39
39
 
40
+ # @return [Integer, nil]
41
+ attr_accessor :modifier_after_one_and_a_half
42
+
40
43
  def initialize(rate, modifier)
41
44
  @rate = rate
42
45
  @modifier = modifier
@@ -49,6 +52,7 @@ module BCDice
49
52
  @semi_fixed_val = 0
50
53
  @tmp_fixed_val = 0
51
54
  @modifier_after_half = nil
55
+ @modifier_after_one_and_a_half = nil
52
56
  end
53
57
 
54
58
  # @return [Boolean]
@@ -56,6 +60,11 @@ module BCDice
56
60
  return !@modifier_after_half.nil?
57
61
  end
58
62
 
63
+ # @return [Boolean]
64
+ def one_and_a_half
65
+ return !@modifier_after_one_and_a_half.nil?
66
+ end
67
+
59
68
  # @return [Integer]
60
69
  def min_critical
61
70
  if @semi_fixed_val <= 1