bcdice 3.10.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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -0
  3. data/i18n/FutariSousa/ko_kr.yml +1625 -529
  4. data/i18n/Insane/ko_kr.yml +393 -258
  5. data/i18n/NinjaSlayer2/ja_jp.yml +34 -0
  6. data/lib/bcdice/game_system/DemonSpike.rb +89 -0
  7. data/lib/bcdice/game_system/Emoklore.rb +4 -6
  8. data/lib/bcdice/game_system/FutariSousa_Korean.rb +44 -19
  9. data/lib/bcdice/game_system/GundamSentinel.rb +377 -0
  10. data/lib/bcdice/game_system/HunterTheReckoning5th.rb +10 -3
  11. data/lib/bcdice/game_system/Insane_Korean.rb +11 -11
  12. data/lib/bcdice/game_system/KamitsubakiCityUnderConstructionNarrative.rb +251 -0
  13. data/lib/bcdice/game_system/MamonoScramble.rb +98 -0
  14. data/lib/bcdice/game_system/NinjaSlayer.rb +3 -1
  15. data/lib/bcdice/game_system/NinjaSlayer2.rb +299 -0
  16. data/lib/bcdice/game_system/RuneQuestRoleplayingInGlorantha.rb +170 -0
  17. data/lib/bcdice/game_system/SajinsenkiAGuS.rb +5 -1
  18. data/lib/bcdice/game_system/SajinsenkiAGuS2E.rb +285 -0
  19. data/lib/bcdice/game_system/SkynautsBouken.rb +1 -1
  20. data/lib/bcdice/game_system/SwordWorld.rb +16 -0
  21. data/lib/bcdice/game_system/SwordWorld2_5.rb +8 -1
  22. data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +10 -4
  23. data/lib/bcdice/game_system/WerewolfTheApocalypse5th.rb +173 -0
  24. data/lib/bcdice/game_system/ZombiLine.rb +115 -0
  25. data/lib/bcdice/game_system/sword_world/rating_options.rb +3 -0
  26. data/lib/bcdice/game_system/sword_world/rating_parsed.rb +9 -0
  27. data/lib/bcdice/game_system/sword_world/rating_parser.rb +173 -128
  28. data/lib/bcdice/game_system/sword_world/transcendent_test.rb +1 -1
  29. data/lib/bcdice/game_system.rb +9 -0
  30. data/lib/bcdice/version.rb +1 -1
  31. metadata +13 -3
@@ -0,0 +1,34 @@
1
+ ja_jp:
2
+ NinjaSlayer2:
3
+ table:
4
+ SATSUBATSU:
5
+ name: "サツバツ!!(D6) > "
6
+ type: 1D6
7
+ items:
8
+ - "「イヤーッ!」腹部に強烈な一撃が命中! 敵はくの字に折れ曲がり、ワイヤーアクションめいて吹っ飛んだ! \n『痛打+1』。敵の【体力】を減らした場合、付属効果として『弾き飛ばし』を与える。"
9
+ - "「観念してハイクを詠め!」頭部への痛烈なカラテが命中! 眼球破壊もしくは激しい脳震盪が敵を襲う! \n『痛打+1』。敵の【体力】を減らした場合、付属効果として『ニューロンダメージ2』と『ワザマエダメージ1』と『●部位損傷:頭部』を与える。"
10
+ - "「苦しみ抜いて死ぬがいい!」急所や内臓を情け容赦なく破壊! \n『痛打+1』。敵の【体力】を減らした場合、付属効果として『ニューロンダメージ1』と『精神力ダメージ2』と『●部位損傷:胴体』を与える。"
11
+ - "「どこへ逃げても無駄だ!」敵の脚を無慈悲に粉砕! \n『痛打+1』。敵の【体力】を減らした場合、付属効果として『カラテダメージ1』と『脚力ダメージ2』と『●部位損傷:脚部』を与える。"
12
+ - "「これで手も足も出まい!」敵の両腕をダブルチョップ切断! 傷口から鮮血がスプリンクラーめいて噴き出す! \n『痛打+1』。敵の【体力】を減らした場合、付属効果として『カラテダメージ2』と『ワザマエダメージ2』と『●部位損傷:腕部』を与える。"
13
+ - "「さらばだ! イイイヤアアアアーーーーッ!」ヤリめいたチョップが敵の胸を貫通! さらに心臓を掴み取り、握りつぶした! ゴウランガ! \n『即死!』。敵が『即死耐性』を持つ場合、この効果は『痛打+2D6』に置き換えられる。"
14
+ WASSHOI:
15
+ name: "ニンジャスレイヤー=サンのエントリー!!(D6) > "
16
+ type: 1D6
17
+ items:
18
+ - "高所からの回転着地! タタミ四枚の距離で睨み合った! \n標的ニンジャから3または4マス離れた任意のマスに、【殺】コマを置くこと。"
19
+ - "ドアを蹴破って出現! \n標的ニンジャがいる部屋の任意のドアの隣に【殺】コマを置くこと。 \nなお、ドアにあらかじめ鍵をかけるなどの行為は全て無駄である。"
20
+ - "KRAAAAASH! 窓を突き破り出現! \n標的ニンジャがいる部屋の任意の窓の隣に【殺】コマを置くこと。 \n【殺】コマが隣接している間、その窓は脱出用として使用できなくなる。"
21
+ - "天井破壊や床破砕、または垂直リフト射出により出現! \n標的ニンジャから2マス離れた任意の場所に【殺】コマを置くこと。 \n激しい恐怖や動揺により、次のターンの終了時まで、その場にいる【DKK】1以上のニンジャ全員は『連続側転判定』の難易度が+1される。"
22
+ - "冷蔵庫や金庫から突如出現! \nそのマップ上に存在するトレジャーボックス内に、ニンジャスレイヤーが潜んでいた。標的ニンジャから最も近いトレジャーボックス1個(もしくは適切な障害物や爆発物)の隣に【殺】コマを置くこと。 \n激しい恐怖や動揺により、次のターンの終了時まで、その場にいる【DKK】1以上のニンジャ全員は『連続側転判定』の難易度が+1される。"
23
+ - "「行き先はジゴクですよ」 \nマップ上にいるNPC1人(標的ニンジャから最も近くにいる者)が、実はニンジャスレイヤーの変装であった。そのNPCのコマを【殺】に変更せよ(本物のNPCがどこにいったのかはニンジャマスターが後で考える)。 \n激しい恐怖や動揺により、次のターンの終了時まで、その場にいる【DKK】1以上のニンジャ全員は『連続側転判定』の難易度が+2される。"
24
+ NRS:
25
+ name: "ニンジャ・リアリティ・ショック発症(D7) > "
26
+ type: 1D7
27
+ items:
28
+ - "絶叫 \n恐怖のあまり、その場で絶叫を上げる。 \n探索中の場合、近くの敵に存在を気づかれる可能性がある(シナリオ次第)。 \n戦闘中の場合、恐怖のあまり足がガクガクと震え、このターン終了まで【脚力】が0となり、『崩れ状態』とみなされる。"
29
+ - "失禁 \n恐怖とトラウマのあまりその場で立ちすくみ、失禁する。自尊心を失い【精神力】が-1される。 \n戦闘中の場合、足がすくんで手がブルブルと震え、このターン終了まであらゆる自発的行動の難易度が+1され、【脚力】が1となり、『崩れ状態』とみなされる。"
30
+ - "パニック逃走や異常行動 \n恐怖のあまり絶叫し、仲間を見捨ててその場から全速力で逃げ出そうとしたり、銃を持っている場合は見えない敵に向かって乱射しようとする。 \nあるいは仲間のことをニンジャだと思い込んで攻撃を仕掛けたり、理解不能な異常行動を取ったりする。 \n探索シーケンスの場合、直ちに戦闘シーケンスが発生してこのPCの手番となり、1ターンだけマスターがこのPCを操作する。このPCは常軌を逸した身体能力を発揮し、【脚力】6として行動する。マスターはこのPCに自傷行為以外のどんな行動を取らせてもよい。このPCにとっては、あらゆるキャラが敵とみなされる。このターンの終了時に、このPCは正気に戻る。 \n戦闘中の場合も同様で、次の手番にこの状態となる。手番開始時に攻撃できる相手がニンジャしか見えていない場合、逃走を優先する。"
31
+ - "ドゲザ \n失禁し【精神力】に1ダメージ。突然ドゲザによる命乞いを行うため、このターン終了時まで『麻痺状態』とみなされる。"
32
+ - "激しい嘔吐や鼻血 \n【体力】と【精神力】にそれぞれ1ダメージを受ける。 \n戦闘中の場合、このターンのあらゆる判定難易度が+1される。 \nしかし目の前の脅威に立ち向かおうとする意志は砕けていない。"
33
+ - "気絶 \n失禁し【精神力】に1ダメージ。さらに打ち上げられたマグロめいてその場で倒れて口をパクパクとさせ、『気絶状態』となる。 \n戦闘が終了するか、一定時間が経過するか、誰かに蘇生してもらうまで、この状態は解除されない。"
34
+ - "心臓発作や狂死 \n急激なニンジャリアリティショックに耐えきれず、PCは心臓発作やニューロン損傷を起こして【体力】0となり、その場に倒れ『気絶状態』となる。 \nZBRアドレナリンでなければ蘇生できない。処置を受けずに時間が経過すると死亡する。"
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class DemonSpike < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'DemonSpike'
8
+
9
+ # ゲームシステム名
10
+ NAME = 'デモンスパイク'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'てもんすはいく'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
17
+ ・行為判定 xDS+y
18
+  行為判定を行い、達成値、成否、成功度を出力する。
19
+  x: ダイス数(省略:2)
20
+  y: 能力値やスパイク能力による達成値の修正(省略可)
21
+ INFO_MESSAGE_TEXT
22
+
23
+ register_prefix('\d*DS')
24
+
25
+ def eval_game_system_specific_command(command)
26
+ roll_action(command)
27
+ end
28
+
29
+ private
30
+
31
+ def roll_action(command)
32
+ parser = Command::Parser.new("DS", round_type: @round_type)
33
+ .enable_prefix_number
34
+ .restrict_cmp_op_to(nil)
35
+ parsed = parser.parse(command)
36
+ unless parsed
37
+ return nil
38
+ end
39
+
40
+ parsed.prefix_number ||= 2
41
+ if parsed.prefix_number < 2
42
+ return nil
43
+ end
44
+
45
+ step = roll_step(parsed.prefix_number)
46
+ step_list = [step]
47
+ while step[:dice_sum] == 10
48
+ step = roll_step(parsed.prefix_number)
49
+ step_list.push(step)
50
+ end
51
+
52
+ is_fumble = step_list[0][:dice_sum] == 2
53
+ total = is_fumble ? 0 : step_list.sum { |s| s[:dice_sum] } + parsed.modify_number
54
+ success_level = total / 10
55
+ is_success = total >= 10
56
+
57
+ res =
58
+ if is_success
59
+ "成功, 成功度#{success_level}"
60
+ elsif is_fumble
61
+ "自動的失敗"
62
+ else
63
+ "失敗"
64
+ end
65
+
66
+ sequence = [
67
+ "(#{parsed})",
68
+ step_list.map { |s| "#{s[:dice_sum]}[#{s[:dice_list].join(',')}]" },
69
+ total,
70
+ res,
71
+ ].flatten
72
+
73
+ return Result.new.tap do |r|
74
+ r.condition = is_success
75
+ r.critical = step_list.length > 1
76
+ r.fumble = is_fumble
77
+ r.text = sequence.join(" > ")
78
+ end
79
+ end
80
+
81
+ def roll_step(times)
82
+ dice_list = @randomizer.roll_barabara(times, 6).sort.reverse
83
+ dice_sum = (dice_list[0] + dice_list[1]).clamp(2, 10)
84
+
85
+ return {dice_list: dice_list, dice_sum: dice_sum}
86
+ end
87
+ end
88
+ end
89
+ end
@@ -57,14 +57,12 @@ module BCDice
57
57
  def dice_roll(num_dice, success_threshold)
58
58
  # ダイスを振った結果を配列として取得
59
59
  values = @randomizer.roll_barabara(num_dice, 10)
60
- values_without_critical = values.reject { |num| num <= CRITICAL_VALUE }
61
-
62
- critical = values.size - values_without_critical.size
63
- success = values_without_critical.count { |num| num <= success_threshold }
64
- fumble = values_without_critical.count { |num| num >= FUMBLE_VALUE }
60
+ critical = values.count(CRITICAL_VALUE)
61
+ success = values.count { |num| num <= success_threshold }
62
+ fumble = values.count(FUMBLE_VALUE)
65
63
 
66
64
  # 成功値
67
- success_value = 2 * critical + success - fumble
65
+ success_value = critical + success - fumble
68
66
  result = compare_result(success_value)
69
67
 
70
68
  result.text = "#{values} > #{success_value} > #{translate('Emoklore.success_count', count: success_value)} #{result.text}"
@@ -9,7 +9,7 @@ module BCDice
9
9
  ID = 'FutariSousa:Korean'
10
10
 
11
11
  # ゲームシステム名
12
- NAME = '둘이서 수사(후타리소우사)'
12
+ NAME = '둘이서 수사'
13
13
 
14
14
  # ゲームシステム名の読みがな
15
15
  SORT_KEY = '国際化:Korean:둘이서 수사'
@@ -17,26 +17,51 @@ module BCDice
17
17
  # ダイスボットの使い方
18
18
  HELP_MESSAGE = <<~MESSAGETEXT
19
19
  ・판정용 커맨드
20
- 탐정용:【DT】…10면체 주사위를 2개 굴려 판정합니다.『유리』라면【3DT】, 『불리』라면【1DT】를 사용합니다.
21
- 조수용:【AS】…6면체 주사위를 2개 굴려 판정합니다. 『유리』라면【3AS】, 『불리』라면【1AS】를 사용합니다.
20
+ 탐정용:【DT】…10면체 주사위를 2개 굴려 판정합니다.『유리함』이라면【3DT】, 『불리함』이라면【1DT】를 사용합니다.
21
+ 조수용:【AS】…6면체 주사위를 2개 굴려 판정합니다. 『유리함』이라면【3AS】, 『불리함』이라면【1AS】를 사용합니다.
22
+  
22
23
  ・각종표
23
- 【조사】
24
- 이상한 버릇 결정표 SHRD
25
-  지껄이다표  SHFM/강압적인 수사표  SHBT/시치미 떼기표   SHPI
26
-  사건에 몰두표 SHEG/파트너와……표  SHWP/무언가 하고 있다표 SHDS
27
-  기상천외표  SHFT/갑작스런 번뜩임표 SHIN/희노애락표     SHEM
28
- 이벤트표
29
-  현장에서  EVS/어째서? EVW/협력자와 함께 EVN
30
-  상대쪽에서 EVC/VS용의자 EVV
31
- 조사의 장애표 OBT  변조표 ACT  목격자표 EWT  미제사건표 WMT
24
+ 【세션 시】
25
+ 기벽 결정 SHRD
26
+  발언 표       SHFM/수사 강행 표     SHBT/시치미 표       SHPI
27
+  사건에 몰두 표    SHEG/파트너와…… 표     SHWP/뭔가 하고 있음 표   SHDS
28
+  기상천외 표     SHFT/갑작스런 영감 표    SHIN/희노애락 표      SHEM
29
+  인간 모방 표     SHHE/인간 모방 실패 표   SHHF/파트너를 향한 장난 표 SHMP
30
+  의미심장 표     SHSB/초조함 표       SHFR/갑자기 왜그래 표   SHIS
31
+  억지 요구 표    SHSE/멀쩡해 보임 표     SHLM/질투에 사로잡힘 표   SHJS
32
+  오만한 태도 표   SHAR/비교적 가벼운 행동 표 SHRM/노 타임 표      SHNT
33
+  수사 방식 표    SHIM/귀족 표        SHNO/설명하지 않음 표   SHNE
34
+  형사 특유의 습관 표 SHHD
35
+  
36
+ 이벤트 표
37
+  현장에서 EVS/왜? EVW/협력자와 함께 EVN
38
+  알아서 찾아온 단서 EVC/VS용의자 EVV
39
+  폐쇄 공간 EVE
40
+  탐정 혼자 수사 EVD/조수 혼자 수사 EVA/관광 수사 EVT
41
+  예상치 못한 힌트 EVH/실험을 해보자 EVX/게스트 수사 EVG
42
+  형사 탐문 수사 EVQ/형사 대규모 수사 EVM/비밀스러운 정보 교환 EVP
43
+  동료들과 함께 수사 EVO/단골 가게 시추에이션 EVF/하드B 형사 액션 EVB
44
+  탐정을 얌전하게 만드는 수사 EVL/전통적 수사 EVZ/원시적 수사 EVR
45
+  
46
+ 감정 표
47
+  감정 표A/B   FLT66・FLT10
48
+  마음에 드는 점  FLTL66 /마음에 안 드는 점  FLTD66
49
+  무작위 감정 결정 표(당친법)  FLTRA
50
+  얼굴 부위       FLTF66/신체 부위      FLTB66/생활 습관    FLTH66
51
+  마음이 들뜨는 감각   FLTS66/타인에 대한 태도  FLTA66/헤비 웨이트   FLTW66
52
+  동료          FLTC66/부하        FLTU66/상사     FLTO66
53
+  수사 방식 FLTI66
54
+ 조사 방해 요인 표 OBT  상태 이상 표 ACT  목격자 표 EWT  미제 사건 표 WMT
55
+ 추억의 물품 결정 표 MIT  에피소드 동반 추억의 물품 결정 표 MITE  
56
+ 호칭 표A・B  NCT66・NCT10
57
+  
32
58
  【설정】
33
- 배경표
34
-  탐정 운명의 혈통  BGDD/천상의 재능  BGDG/마니아    BGDM
35
-  조수 정의로운 사람 BGAJ/정렬적인 사람 BGAP/말려든 사람 BGAI
36
- 신장표 HT  아지트표 BT  관계표 GRT  추억의 물건 결정표 MIT
37
- 직업표A・B  JBT66・JBT10  패션 특징표A・B    FST66・FST10
38
- 감정표A・B  FLT66・FLT10  좋아하는 것/싫어하는 것표A・B LDT66・LDT10
39
- 호칭표A・B NCT66・NCT10
59
+ 배경 표
60
+  탐정 운명의 혈통  BGDD/천성적인 재능  BGDG/마니아   BGDM
61
+  조수 정의로운 사람 BGAJ/정열적인 사람  BGAP/말려든 사람 BGAI
62
+ 신장 HT  아지트 BT  관계 GRT
63
+ 직업 표A・B  JBT66・JBT10  패션 특징 표A・B  FST66・FST10
64
+ 호불호 표A・B  LDT66・LDT10
40
65
  MESSAGETEXT
41
66
 
42
67
  register_prefix_from_super_class()
@@ -0,0 +1,377 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class GundamSentinel < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'GundamSentinel'
8
+
9
+ # ゲームシステム名
10
+ NAME = 'ガンダム・センチネルRPG'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'かんたむせんちねる'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
17
+ ・基本戦闘(BB, BBM)
18
+  BB[+修正][>回避値]で基本戦闘を判定します。回避値を指定すると、命中・回避も表示します。
19
+  BBM[+修正][>回避値]でモブ用の基本戦闘を判定します。クリティカルを判定します。回避値を指定すると、命中・回避も表示します。
20
+
21
+  例)BB BBM BB+5>14 BBM+5>15
22
+
23
+ ・一般技能(GS)
24
+  GS[+修正][>目標値]で一般技能を判定します。目標値を指定しない場合は、目標値10で判定します。
25
+
26
+  例)GS GS+5 GS+5>10
27
+
28
+
29
+ ・各種表
30
+  敵MSクリティカルヒットチャート (ECHC)
31
+  PC用脱出判定チャート      (PEJC[+m] m:修正)
32
+  艦船追加ダメージ決定チャート  (ASDC)
33
+  対空砲結果チャート       (AARC[+m]=t m:修正, t:対空防御力)
34
+  リハビリ判定チャート      (RTJC[+m] m:修正)
35
+  二次被害判定チャート      (SDDC)
36
+ INFO_MESSAGE_TEXT
37
+
38
+ def initialize(command)
39
+ super(command)
40
+
41
+ @round_type = RoundType::CEIL
42
+ @d66_sort_type = D66SortType::NO_SORT
43
+ end
44
+
45
+ def eval_game_system_specific_command(command)
46
+ roll_basic_battle(command) ||
47
+ roll_general_skill(command) ||
48
+ roll_anti_aircraft_gun_result_chart(command) ||
49
+ roll_escape_chart(command) ||
50
+ roll_rehabilitation_chart(command) ||
51
+ roll_tables(command, TABLES)
52
+ end
53
+
54
+ private
55
+
56
+ # 基本戦闘ロール
57
+ def roll_basic_battle(command)
58
+ m = /^BB(M)?([-+][-+\d]+)?(>([-+\d]+))?/.match(command)
59
+ return nil unless m
60
+
61
+ mob = m[1]
62
+ modify = ArithmeticEvaluator.eval(m[2])
63
+ have_modify = false
64
+ have_modify = true if m[2]
65
+ avoid = ArithmeticEvaluator.eval(m[4])
66
+ have_avoid = false
67
+ have_avoid = true if m[4]
68
+
69
+ d60 = @randomizer.roll_once(6)
70
+ d06 = @randomizer.roll_once(6)
71
+ total_d = d60 * 10 + d06
72
+ d60 += (d06 + modify - 1).div(6)
73
+ d06 = (d06 + modify - 1).modulo(6) + 1
74
+ total = d60 * 10 + d06
75
+ total = 11 if total < 11
76
+
77
+ success = false
78
+ failure = false
79
+ critical = false
80
+
81
+ modify_label = nil
82
+ if have_modify
83
+ if modify >= 0
84
+ modify_label = "#{total_d}+#{modify}"
85
+ else
86
+ modify_label = "#{total_d}#{modify}"
87
+ end
88
+ end
89
+
90
+ critical_label = nil
91
+ if mob && (total >= 66)
92
+ critical_label = "クリティカル"
93
+ critical = true
94
+ end
95
+
96
+ result = nil
97
+ if have_avoid
98
+ if total > avoid
99
+ result = "命中(+" + count_success(total, avoid).to_s + ")"
100
+ success = true
101
+ else
102
+ result = "回避"
103
+ failure = true
104
+ end
105
+ end
106
+
107
+ sequence = [
108
+ "(#{command})",
109
+ modify_label,
110
+ total,
111
+ result,
112
+ critical_label,
113
+ ].compact
114
+
115
+ Result.new(sequence.join(" > ")).tap do |r|
116
+ r.success = success
117
+ r.failure = failure
118
+ r.critical = critical
119
+ end
120
+ end
121
+
122
+ def count_success(dice, avoid)
123
+ d60 = dice.div(10)
124
+ d06 = dice.modulo(10)
125
+ a60 = avoid.div(10)
126
+ a06 = avoid.modulo(10)
127
+
128
+ return ((d60 * 6 + d06) - (a60 * 6 + a06))
129
+ end
130
+
131
+ # 一般技能ロール
132
+ def roll_general_skill(command)
133
+ m = /^GS([-+][-+\d]+)?(>([-+\d]+))?/.match(command)
134
+ return nil unless m
135
+
136
+ modify = ArithmeticEvaluator.eval(m[1])
137
+ have_modify = false
138
+ have_modify = true if m[1]
139
+ target = ArithmeticEvaluator.eval(m[3])
140
+ target = 10 unless m[3]
141
+
142
+ success = false
143
+ failure = false
144
+
145
+ dice = @randomizer.roll_sum(2, 6)
146
+
147
+ modify_label = nil
148
+ if have_modify
149
+ if modify >= 0
150
+ modify_label = "#{dice}+#{modify}"
151
+ else
152
+ modify_label = "#{dice}#{modify}"
153
+ end
154
+ end
155
+ total = dice + modify
156
+ if total > target
157
+ result = "成功"
158
+ success = true
159
+ else
160
+ result = "失敗"
161
+ failure = true
162
+ end
163
+
164
+ sequence = [
165
+ "(#{command})",
166
+ modify_label,
167
+ total,
168
+ result,
169
+ ].compact
170
+
171
+ Result.new(sequence.join(" > ")).tap do |r|
172
+ r.success = success
173
+ r.failure = failure
174
+ end
175
+ end
176
+
177
+ # 各種表
178
+
179
+ # 対空砲結果チャート
180
+ GUN_RESULT_CHART = [
181
+ ["D", "H", "H", "H", 10, 8, 6, 5, 4, 2, 1, "-", "-"],
182
+ ["D", "H", "H", "H", 12, 10, 9, 8, 6, 5, 3, 2, "-"],
183
+ ["D", "D", "H", "H", "H", 12, 10, 9, 7, 6, 4, 3, 1],
184
+ ["D", "D", "H", "H", "H", 14, 13, 12, 10, 8, 6, 5, 3],
185
+ ["D", "D", "D", "H", "H", "H", 14, 13, 11, 9, 7, 6, 4],
186
+ ["D", "D", "D", "H", "H", "H", "H", 16, 14, 12, 11, 8, 6],
187
+ ].freeze
188
+
189
+ def roll_anti_aircraft_gun_result_chart(command)
190
+ parser = Command::Parser.new("AARC", round_type: @round_type).restrict_cmp_op_to(:==)
191
+ parsed = parser.parse(command)
192
+
193
+ return nil unless parsed
194
+
195
+ target = parsed.target_number.clamp(1, 6)
196
+ dice = @randomizer.roll_sum(2, 6)
197
+ total = (dice + parsed.modify_number).clamp(1, 13)
198
+
199
+ cmd =
200
+ if parsed.modify_number != 0
201
+ "(#{dice}#{Format.modifier(parsed.modify_number)}=#{total})"
202
+ else
203
+ total.to_s
204
+ end
205
+ result = GUN_RESULT_CHART[target - 1][total - 1]
206
+
207
+ Result.new().tap do |r|
208
+ r.text = "対空砲結果チャート(#{cmd}vs#{target}) > 結果「#{result}」"
209
+ r.condition = result.is_a?(Integer)
210
+ end
211
+ end
212
+
213
+ # PC用脱出判定チャート
214
+ ESCAPE_CHART = [
215
+ '*',
216
+ '*',
217
+ '無傷で脱出',
218
+ '無傷で脱出',
219
+ '無傷で脱出',
220
+ '軽傷で脱出「1D6ダメージ。」',
221
+ '中傷で脱出「2D6ダメージ。」',
222
+ '重傷で脱出「3D6ダメージ。」',
223
+ '重体で脱出「1D3の耐久力が残る。」',
224
+ '戦死「二階級特進。」',
225
+ '戦死「二階級特進。」',
226
+ '戦死「二階級特進。」',
227
+ '戦死「二階級特進。」',
228
+ ].freeze
229
+
230
+ def roll_escape_chart(command)
231
+ parser = Command::Parser.new("PEJC", round_type: @round_type).restrict_cmp_op_to(nil)
232
+ parsed = parser.parse(command)
233
+ return nil unless parsed
234
+
235
+ dice = @randomizer.roll_sum(2, 6)
236
+ total = (dice + parsed.modify_number).clamp(2, 12)
237
+
238
+ cmd =
239
+ if parsed.modify_number != 0
240
+ "#{dice}#{Format.modifier(parsed.modify_number)}=#{total}"
241
+ else
242
+ total.to_s
243
+ end
244
+ result = ESCAPE_CHART[total]
245
+
246
+ Result.new("PC用脱出判定チャート(#{cmd}) > #{result}")
247
+ end
248
+
249
+ REHABILITATION_CHART = [
250
+ '*',
251
+ '*',
252
+ 'なし',
253
+ '1ヶ月',
254
+ '2ヶ月',
255
+ '3ヶ月',
256
+ '4ヶ月',
257
+ '5ヶ月',
258
+ '6ヶ月',
259
+ '10ヶ月',
260
+ '1年',
261
+ '1年6ヶ月',
262
+ '1年と、もう一度このチャートで振った結果分を足した期間',
263
+ ].freeze
264
+
265
+ def roll_rehabilitation_chart(command)
266
+ parser = Command::Parser.new("RTJC", round_type: @round_type).restrict_cmp_op_to(nil)
267
+ parsed = parser.parse(command)
268
+ return nil unless parsed
269
+
270
+ dice = @randomizer.roll_sum(2, 6)
271
+ total = (dice + parsed.modify_number).clamp(2, 12)
272
+
273
+ cmd =
274
+ if parsed.modify_number != 0
275
+ "#{dice}#{Format.modifier(parsed.modify_number)}=#{total}"
276
+ else
277
+ total.to_s
278
+ end
279
+ result = REHABILITATION_CHART[total]
280
+
281
+ Result.new("リハビリ判定チャート(#{cmd}) > #{result}")
282
+ end
283
+
284
+ TABLES = {
285
+ 'ECHC' => DiceTable::Table.new(
286
+ '敵MSクリティカルヒットチャート',
287
+ '2D6',
288
+ [
289
+ 'コックピット直撃:目標MSは残骸となる。',
290
+ '腕破損:同時に携帯武器も失う。携帯武装の交換も行えない。直ちにモラル判定を-4で行う。',
291
+ '射撃武装破損:目標MSはその時点で使用しているナンバーの若い武装を1つ失う。全ての武装を失った場合、モラル判定を行う。',
292
+ '頭部直撃:目標MSはメインカメラを失い、以後射撃、格闘の命中判定に-6の修正を受ける。頭部に装備されている武装も失われる。',
293
+ 'パイロット気絶:目標MSは回復するまで行動不能。',
294
+ '目標MSへのダメージ2倍。',
295
+ '目標MSへのダメージ2倍。',
296
+ '目標MSへのダメージ3倍。',
297
+ '脚破損:目標MSは、以後の回避値に-6の修正を受ける。',
298
+ 'コントロール不能:目標MSは1D6ラウンドの間、行動不能。',
299
+ '熱核ジェネレーター直撃:目標MSは直ちに爆発(耐久力0)する。',
300
+ ]
301
+ ),
302
+ 'ASDC' => DiceTable::Table.new(
303
+ '艦船追加ダメージ決定チャート',
304
+ '2D6',
305
+ [
306
+ 'ブリッジ損傷「複数ある艦は、総てのブリッジが損傷すると以後の対空防御は修正を+5する。」',
307
+ 'カタパルト損傷「複数ある艦は、総てのカタパルトが損傷すると、MSの発着艦ができなくなる。」',
308
+ '追加ダメージ「追加2D6×2ダメージ。」',
309
+ '主砲大破「主砲1門を失う。」',
310
+ '副砲大破「副砲1門を失う。」',
311
+ '追加ダメージ「追加2D6ダメージ。」',
312
+ '追加ダメージ「追加2D6ダメージ。」',
313
+ '追加ダメージ「追加2D6ダメージ。」',
314
+ '1ターン行動不能「1ターンはその艦は何も行動ができない。」',
315
+ '航行不能「その艦はそのヘックスから動けなくなる。」',
316
+ 'エンジン誘爆「1D6×10%の耐久力を失う。」',
317
+ ]
318
+ ),
319
+ 'SDDC' => DiceTable::D66GridTable.new(
320
+ '二次被害判定チャート',
321
+ [
322
+ [
323
+ '奇蹟的に無傷「不発!?今回のダメージは0。」',
324
+ 'メインカメラ破損「以後、射撃、格闘の命中判定に-3の修正を受ける。」',
325
+ 'コクピット破損「以後の追加ダメージ判定に-1の修正を受ける。」',
326
+ '右腕損傷「携帯していた武装も失う。また右腕での武器の使用はできなくなる。」',
327
+ '左腕損傷「携帯していた武装も失う。また左腕での武器の使用はできなくなる。」',
328
+ '気絶「気絶判定の余地無く、必ず気絶する。」',
329
+ ],
330
+ [
331
+ '気絶「気絶判定を-6の修正で行う。」',
332
+ '気絶「気絶判定を-4の修正で行う。」',
333
+ '気絶「気絶判定を-2の修正で行う。」',
334
+ '気絶「気絶判定を行う。」',
335
+ '予備弾倉破損「携帯している予備弾倉かEパックを1つ失う。」',
336
+ 'サブカメラ破損「以後、射撃、格闘の命中判定に-1の修正を受ける。」',
337
+ ],
338
+ [
339
+ '固定武装破損「固定されている武装を1つ失う。」',
340
+ '予備武装破損「携帯している以外の武装を1つ失う。」',
341
+ '頭部破損「メインカメラも失い、以後、射撃、格闘の命中判定に-3の修正を受ける。」',
342
+ '右脚破損「以後、回避値が1D3低下する。」',
343
+ '左脚破損「以後、回避値が1D3低下する。」',
344
+ '操縦機構破損「以後、すべての行動は消費行動ポイントを1ポイント余分に消費する。」',
345
+ ],
346
+ [
347
+ '軽傷「パイロットは1D6のダメージを受ける。また気絶判定を行う。」',
348
+ '中傷「パイロットは2D6のダメージを受ける。また気絶判定を-6修正で行う。」',
349
+ '重傷「パイロットは3D6のダメージを受ける。また気絶判定を-9修正で行う。」',
350
+ '操縦伝達部破損「以後すべての射撃、格闘の命中判定と回避値に-1の修正を受ける。」',
351
+ 'センサー破損「イニシアティブ決定に-1の修正を受ける。」',
352
+ '脱出機構破損「脱出判定に+3の修正を受ける。」',
353
+ ],
354
+ [
355
+ '熱核ジェネレーター損傷「行動の「追加移動」が行えなくなる。」',
356
+ '右腕の携帯武装破損「右腕に持っていた武装を1つ失う。」',
357
+ '左腕の携帯武装破損「左腕に持っていた武装を1つ失う。」',
358
+ 'サブスラスター破損「回避値が1低下する。」',
359
+ 'プロペラントタンク破損「プロペラントタンクを1つ失う。」',
360
+ 'バックパック破損「推進剤3D6ポイント失う。」',
361
+ ],
362
+ [
363
+ 'メインスラスター破損「回避値が1D6低下する。」',
364
+ '動力パイプ破損「以後、行動ポイント決定のダイスに-1の修正を受ける。」',
365
+ '動力伝達機構破損「以後、行動ポイント決定のサイコロに-1D3の修正を受ける。」',
366
+ 'サブスラスター破損「旋回が120度までしかできなくなる。」',
367
+ 'メインスラスター破損「旋回が60度までしかできなくなる。」',
368
+ '熱核ジェネレーター直撃「そのMSは爆発する。PCは直ちに脱出判定を行う。」',
369
+ ]
370
+ ]
371
+ ),
372
+ }.freeze
373
+
374
+ register_prefix('BBM?', 'GS', 'AARC', 'PEJC', 'RTJC', TABLES.keys)
375
+ end
376
+ end
377
+ end
@@ -17,12 +17,12 @@ module BCDice
17
17
  ・判定コマンド(nHRFx+x)
18
18
  注意:難易度は必要成功数を表す
19
19
 
20
- 難易度指定:成功数のカウント、判定成功と失敗、Critical処理、Critical Winのチェックを行う
20
+ 難易度指定:成功数のカウント、判定成功と失敗、Critical処理、Critical Win、Total Failureのチェックを行う
21
21
  (Desperationダイスがある場合)OverreachとDespairの発生チェックを行う
22
22
  例) (難易度)HRF(通常ダイス)+(Desperationダイス)
23
23
  (難易度)HRF(通常ダイス)
24
24
 
25
- 難易度省略:成功数のカウント、判定失敗、Critical処理、(Desperationダイスがある場合)Despairチェックを行う
25
+ 難易度省略:成功数のカウント、判定失敗、Critical処理、Total Failure、(Desperationダイスがある場合)Despairチェックを行う
26
26
  判定成功、Overreachのチェックを行わない
27
27
  Critical Win、(Desperationダイスがある場合)Despair、Overreachのヒントを出力
28
28
  例) HRF(通常ダイス)+(Desperationダイス)
@@ -56,6 +56,10 @@ module BCDice
56
56
 
57
57
  desperaton_dice_pool = m[DESPERATION_DICE_INDEX]&.to_i
58
58
  if desperaton_dice_pool
59
+ if desperaton_dice_pool > 5
60
+ return "Desperationダイス指定は5ダイスが最大です。"
61
+ end
62
+
59
63
  desperaton_dice_text, desperaton_success_dice, desperaton_ten_dice, desperaton_botch_dice = make_dice_roll(desperaton_dice_pool)
60
64
 
61
65
  ten_dice += desperaton_ten_dice
@@ -102,6 +106,9 @@ module BCDice
102
106
  if desperaton_botch_dice > 0
103
107
  return Result.fumble("#{result_text}:判定失敗! [Despair]")
104
108
  end
109
+ if success_dice == 0
110
+ return Result.fumble("#{result_text}:判定失敗! [Total Failure]")
111
+ end
105
112
 
106
113
  return Result.failure("#{result_text}:判定失敗!")
107
114
  end
@@ -111,7 +118,7 @@ module BCDice
111
118
  return Result.fumble("#{result_text}:判定失敗! [Despair]")
112
119
  end
113
120
 
114
- return Result.failure("#{result_text}:判定失敗!")
121
+ return Result.fumble("#{result_text}:判定失敗! [Total Failure]")
115
122
  else
116
123
  if desperaton_botch_dice > 0
117
124
  result_text = "#{result_text}\n 判定失敗なら [Despair]"