Class: BCDice::GameSystem::BattleTech

Inherits:
Base
  • Object
show all
Defined in:
lib/bcdice/game_system/BattleTech.rb

Defined Under Namespace

Classes: HitPart, UnknownXRMError

Constant Summary collapse

ID =

ゲームシステムの識別子

'BattleTech'
NAME =

ゲームシステム名

'バトルテック'
SORT_KEY =

ゲームシステム名の読みがな

'はとるてつく'
HELP_MESSAGE =

ダイスボットの使い方

<<~MESSAGETEXT
  ・判定方法
   (回数)BT(ダメージ)(部位)+(基本値)>=(目標値)
   回数は省略時 1固定。
   部位はC(正面)R(右)、L(左)。省略時はC(正面)固定
   U(上半身)、L(下半身)を組み合わせ CU/RU/LU/CL/RL/LLも指定可能
   例)BT3+2>=4
    正面からダメージ3の攻撃を技能ベース2目標値4で1回判定
   例)2BT3RL+5>=8
    右下半身にダメージ3の攻撃を技能ベース5目標値8で2回判定
   ミサイルによるダメージは BT(ダメージ)の変わりに SRM2/4/6, LRM5/10/15/20を指定
   例)3SRM6LU+5>=8
    左上半身にSRM6連を技能ベース5目標値8で3回判定
  ・CT:致命的命中表
  ・DW:転倒後の向き表
  ・CDx:メック戦士意識維持表。ダメージ値xで判定 例)CD3
MESSAGETEXT
NO_CRITICAL_HIT_LIMIT =

致命的命中が発生しない上限値

7
LRM_LIMIT =
5
TABLES =

表の集合

{
  'CT' => DiceTable::RangeTable.new(
    '致命的命中表',
    '2D6',
    [
      [2..NO_CRITICAL_HIT_LIMIT, '致命的命中はなかった'],
      [8..9,                     '1箇所の致命的命中'],
      [10..11,                   '2箇所の致命的命中'],
      [12,                       'その部位が吹き飛ぶ(腕、脚、頭)または3箇所の致命的命中(胴)'],
    ]
  ),
  'DW' => DiceTable::Table.new(
    '転倒後の向き表',
    '1D6',
    [
      '同じ(前面から転倒) 正面/背面',
      '1ヘクスサイド右(側面から転倒) 右側面',
      '2ヘクスサイド右(側面から転倒) 右側面',
      '180度逆(背面から転倒) 正面/背面',
      '2ヘクスサイド左(側面から転倒) 左側面',
      '1ヘクスサイド左(側面から転倒) 左側面',
    ]
  )
}.freeze
XRM_DAMAGE_TABLES =

ミサイルダメージ表

{
  'SRM2' => DiceTable::RangeTable.new(
    'SRM2ダメージ表',
    '2D6',
    [
      [2..7,  1],
      [8..12, 2],
    ]
  ),
  'SRM4' => DiceTable::RangeTable.new(
    'SRM4ダメージ表',
    '2D6',
    [
      [2,      1],
      [3..6,   2],
      [7..10,  3],
      [11..12, 4],
    ]
  ),
  'SRM6' => DiceTable::RangeTable.new(
    'SRM6ダメージ表',
    '2D6',
    [
      [2..3,   2],
      [4..5,   3],
      [6..8,   4],
      [9..10,  5],
      [11..12, 6],
    ]
  ),
  'LRM5' => DiceTable::RangeTable.new(
    'LRM5ダメージ表',
    '2D6',
    [
      [2,      1],
      [3..4,   2],
      [5..8,   3],
      [9..10,  4],
      [11..12, 5],
    ]
  ),
  'LRM10' => DiceTable::RangeTable.new(
    'LRM10ダメージ表',
    '2D6',
    [
      [2..3,    3],
      [4,       4],
      [5..8,    6],
      [9..10,   8],
      [11..12, 10],
    ]
  ),
  'LRM15' => DiceTable::RangeTable.new(
    'LRM15ダメージ表',
    '2D6',
    [
      [2..3,    5],
      [4,       6],
      [5..8,    9],
      [9..10,  12],
      [11..12, 15],
    ]
  ),
  'LRM20' => DiceTable::RangeTable.new(
    'LRM20ダメージ表',
    '2D6',
    [
      [2..3,    6],
      [4,       9],
      [5..8,   12],
      [9..10,  16],
      [11..12, 20],
    ]
  )
}.freeze

Instance Attribute Summary

Attributes inherited from Base

#d66_sort_type, #default_cmp_op, #default_target_number, #randomizer, #reroll_dice_reroll_threshold, #round_type, #sides_implicit_d, #upper_dice_reroll_threshold

Instance Method Summary collapse

Methods inherited from Base

#change_text, #check_result, command_pattern, #enable_debug, #enabled_d9?, #eval, eval, #grich_text, #initialize, prefixes_pattern, register_prefix, register_prefix_from_super_class, #sort_add_dice?, #sort_barabara_dice?

Methods included from Translate

#translate

Constructor Details

This class inherits a constructor from BCDice::Base

Instance Method Details

#eval_game_system_specific_command(command) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/bcdice/game_system/BattleTech.rb', line 42

def eval_game_system_specific_command(command)
  result = roll_tables(command, TABLES)
  return result if result

  command = command.gsub("PPC", "BT10")

  count = 1
  if command =~ /^(\d+)(.+)/
    count = Regexp.last_match(1).to_i
    command = Regexp.last_match(2)
  end

  debug('executeCommandCatched count', count)
  debug('executeCommandCatched command', command)

  case command
  when /^CD(\d+)$/
    damage = Regexp.last_match(1).to_i
    return getCheckDieResult(damage)
  when /^((S|L)RM\d+)(.+)/
    tail = Regexp.last_match(3)
    type = Regexp.last_match(1)
    damageFunc = lambda { getXrmDamage(type) }
    return getHitResult(count, damageFunc, tail)
  when /^BT(\d+)(.+)/
    debug('BT pattern')
    tail = Regexp.last_match(2)
    damageValue = Regexp.last_match(1).to_i
    damageFunc = lambda { damageValue }
    return getHitResult(count, damageFunc, tail)
  end

  return nil
rescue UnknownXRMError
  return nil
end

#getBaseValue(baseString) ⇒ Object



131
132
133
134
135
136
137
# File 'lib/bcdice/game_system/BattleTech.rb', line 131

def getBaseValue(baseString)
  base = 0
  return base if baseString.nil?

  base = ArithmeticEvaluator.eval(baseString)
  return base
end

#getCheckDieResult(damage) ⇒ Object



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/bcdice/game_system/BattleTech.rb', line 275

def getCheckDieResult(damage)
  if damage >= 6
    return "死亡"
  end

  table = [[1,  3],
           [2,  5],
           [3,  7],
           [4,  10],
           [5,  11]]

  target = get_table_by_number(damage, table, nil)

  dice1 = @randomizer.roll_once(6)
  dice2 = @randomizer.roll_once(6)
  total = dice1 + dice2
  result = total >= target ? "成功" : "失敗"
  text = "#{total}[#{dice1},#{dice2}]>=#{target}#{result}"

  return text
end

#getDamageInfo(dice, damage, isLrm, index) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
# File 'lib/bcdice/game_system/BattleTech.rb', line 191

def getDamageInfo(dice, damage, isLrm, index)
  return damage, damage.to_s if dice.nil?
  return damage, "[#{dice}] #{damage}" unless isLrm

  currentDamage = damage - (LRM_LIMIT * index)
  if currentDamage > LRM_LIMIT
    currentDamage = LRM_LIMIT
  end

  return currentDamage, currentDamage.to_s
end

#getDamages(damageFunc, partTable, damages) ⇒ Object

Parameters:

  • damageFunc (Proc)

    ダメージを返す手続き

  • partTable (RangeTable)

    命中部位表

  • damages (Hash)

    蓄積したダメージの情報



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/bcdice/game_system/BattleTech.rb', line 160

def getDamages(damageFunc, partTable, damages)
  resultText = ''
  damage, dice, isLrm = damageFunc.call()

  damagePartCount = 1
  if isLrm
    damagePartCount = (1.0 * damage / LRM_LIMIT).ceil
    resultText += "[#{dice}] #{damage}"
  end

  damagePartCount.times do |damageIndex|
    currentDamage, damageText = getDamageInfo(dice, damage, isLrm, damageIndex)

    text, part, criticalText = getHitResultOne(damageText, partTable)
    resultText += " " if isLrm
    resultText += text

    if damages[part].nil?
      damages[part] = {
        partDamages: [],
        criticals: [],
      }
    end

    damages[part][:partDamages] << currentDamage
    damages[part][:criticals] << criticalText unless criticalText.empty?
  end

  return damages, resultText
end

#getHitResult(count, damageFunc, tail) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/bcdice/game_system/BattleTech.rb', line 96

def getHitResult(count, damageFunc, tail)
  m = /([LCR][LU]?)?(\+\d+)?>=(\d+)/.match(tail)
  return nil unless m

  side = m[1] || 'C'
  baseString = m[2]
  target = m[3].to_i
  base = getBaseValue(baseString)
  debug("side, base, target", side, base, target)

  partTable = HitPart::TABLES[side]

  resultTexts = []
  damages = {}
  hitCount = 0

  count.times do
    isHit, hitResult = getHitText(base, target)
    if isHit
      hitCount += 1

      damages, damageText = getDamages(damageFunc, partTable, damages)
      hitResult += damageText
    end
    resultTexts << hitResult
  end

  resultTexts.push("#{hitCount}回命中")

  totalResultText = resultTexts.join("\n")
  totalResultText += " 命中箇所:" + getTotalDamage(damages) if hitCount > 0

  return totalResultText
end

#getHitResultOne(damage_text, hit_part_table) ⇒ Object

攻撃を1回行い、その結果を返す

Parameters:

  • damage_text (String)

    ダメージを表す文字列

  • hit_part_table (RangeTable)

    命中部位表



244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/bcdice/game_system/BattleTech.rb', line 244

def getHitResultOne(damage_text, hit_part_table)
  hit_part_roll_result = hit_part_table.roll(@randomizer)
  hit_part = hit_part_roll_result.content

  critical_hit_may_occur_str =
    hit_part.critical_hit_may_occur ? '(致命的命中)' : ''

  result_parts = [
    [
      "[#{hit_part_roll_result.sum}]",
      "#{hit_part.name}#{critical_hit_may_occur_str}",
      "#{damage_text}",
    ].join(' ')
  ]

  criticalText = ''
  if hit_part.critical_hit_may_occur
    ct_roll_result = TABLES['CT'].roll(@randomizer)

    # 致命的命中が発生したか
    if ct_roll_result.sum > NO_CRITICAL_HIT_LIMIT
      criticalText = ct_roll_result.content
    end

    result_parts.push("[#{ct_roll_result.sum}] #{ct_roll_result.content}")
  end

  # TODO: 構造体で表現する
  return result_parts.join(''), hit_part.name, criticalText
end

#getHitText(base, target) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/bcdice/game_system/BattleTech.rb', line 139

def getHitText(base, target)
  dice1 = @randomizer.roll_once(6)
  dice2 = @randomizer.roll_once(6)
  total = dice1 + dice2 + base
  isHit = (total >= target)
  baseString = (base > 0 ? "+#{base}" : "")

  result = "#{total}[#{dice1},#{dice2}#{baseString}]>=#{target}"

  if isHit
    result += "命中 > "
  else
    result += "外れ"
  end

  return isHit, result
end

#getTotalDamage(damages) ⇒ Object



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/bcdice/game_system/BattleTech.rb', line 203

def getTotalDamage(damages)
  parts = ['',
           '胴中央',
           '右胴',
           '左胴',
           '右脚',
           '左脚',
           '右腕',
           '左腕',]

  allDamage = 0
  damageTexts = []
  parts.each do |part|
    damageInfo = damages.delete(part)
    next if  damageInfo.nil?

    damage = damageInfo[:partDamages].inject(0) { |sum, i| sum + i }
    allDamage += damage
    damageCount = damageInfo[:partDamages].size
    criticals = damageInfo[:criticals]

    text = ""
    text += "#{part}(#{damageCount}回) #{damage}"
    text += " #{criticals.join(' ')}" unless criticals.empty?

    damageTexts << text
  end

  unless damages.empty?
    raise "damages rest!! #{damages.inspect()}"
  end

  result = damageTexts.join("")
  result += " > 合計ダメージ #{allDamage}"

  return result
end

#getXrmDamage(type) ⇒ Object

Raises:



81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/bcdice/game_system/BattleTech.rb', line 81

def getXrmDamage(type)
  raise UnknownXRMError, "unknown XRM: #{type}" unless XRM_DAMAGE_TABLES.key?(type)

  table = XRM_DAMAGE_TABLES[type]
  roll_result = table.roll(@randomizer)

  lrm = type.start_with?('L')
  damage = roll_result.content
  modified_damage = lrm ? damage : (2 * damage)

  return modified_damage, roll_result.sum, lrm
end