lib/bcdice/game_system/Cthulhu7th_ChineseTraditional.rb
# frozen_string_literal: true
module BCDice
module GameSystem
class Cthulhu7th_ChineseTraditional < Base
# ゲームシステムの識別子
ID = 'Cthulhu7th:ChineseTraditional'
# ゲームシステム名
NAME = '克蘇魯神話第7版'
# ゲームシステム名の読みがな
SORT_KEY = '国際化:Chinese Traditional:克蘇魯神話第7版'
# ダイスボットの使い方
HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
・判定 CC(x)<=(目標値)
x:獎勵骰/懲罰骰:Bonus/Penalty Dice (2~-2)。沒有的話可以省略。
致命的失敗:Fumble/失敗:Failure/通常成功:Regular success/
困難成功:Hard success/極限成功:Extreme success/
決定性的成功:Critical success 自動判定。
例)CC<=30 CC(2)<=50 CC(-1)<=75
・組合判定 (CBR(x,y))
進行目標値 x 和 y 的判定。
例)CBR(50,20)
・連射(Full Auto)判定 FAR(w,x,y,z)
w:彈數(1~100)、x:技能値(1~100)、y:故障率
z:獎勵、懲罰骰(-2~2)。可省略。
只計算命中數、貫穿數及剩餘彈藥,不計算傷害。
例)FAR(25,70,98) FAR(50,80,98,-1)
・瘋狂表
・實時型 Short/總結型 Longer
INFO_MESSAGE_TEXT
register_prefix('CC', 'CBR', 'FAR')
def initialize(command)
super(command)
@bonus_dice_range = (-2..2)
end
def eval_game_system_specific_command(command)
case command
when /CC/i
return getCheckResult(command)
when /CBR/i
return getCombineRoll(command)
when /FAR/i
return getFullAutoResult(command)
end
return nil
end
def getCheckResult(command)
nil unless /^CC([-\d]+)?<=(\d+)/i =~ command
bonus_dice_count = Regexp.last_match(1).to_i # 獎勵、懲罰骰數量
diff = Regexp.last_match(2).to_i
return "錯誤。目標值需為1以上。" if diff <= 0
unless @bonus_dice_range.include?(bonus_dice_count)
return "錯誤。獎勵、懲罰骰値為#{@bonus_dice_range.min}~#{@bonus_dice_range.max}。"
end
output = ""
output += "(1D100<=#{diff})"
output += " 獎勵、懲罰骰値[#{bonus_dice_count}]"
units_digit = rollPercentD10
total_list = getTotalLists(bonus_dice_count, units_digit)
total = getTotal(total_list, bonus_dice_count)
result_text = getCheckResultText(total, diff)
output += " > #{total_list.join(', ')} > #{total} > #{result_text}"
return output
end
def rollPercentD10
dice = @randomizer.roll_once(10)
dice = 0 if dice == 10
return dice
end
def getTotalLists(bonus_dice_count, units_digit)
total_list = []
tens_digit_count = 1 + bonus_dice_count.abs
tens_digit_count.times do
bonus = rollPercentD10
total = (bonus * 10) + units_digit
total = 100 if total == 0
total_list.push(total)
end
return total_list
end
def getTotal(total_list, bonus_dice_count)
return total_list.min if bonus_dice_count >= 0
return total_list.max
end
def getCheckResultText(total, diff, fumbleable = false)
if total <= diff
return "決定性的成功" if total == 1
return "極限的成功" if total <= (diff / 5)
return "困難的成功" if total <= (diff / 2)
return "通常成功"
end
fumble_text = "致命的失敗"
return fumble_text if total == 100
if total >= 96
if diff < 50
return fumble_text
else
return fumble_text if fumbleable
end
end
return "失敗"
end
def getCombineRoll(command)
return nil unless /CBR\((\d+),(\d+)\)/i =~ command
diff_1 = Regexp.last_match(1).to_i
diff_2 = Regexp.last_match(2).to_i
total = @randomizer.roll_once(100)
result_1 = getCheckResultText(total, diff_1)
result_2 = getCheckResultText(total, diff_2)
successList = ["決定性的成功", "極限的成功", "困難的成功", "通常成功"]
succesCount = 0
succesCount += 1 if successList.include?(result_1)
succesCount += 1 if successList.include?(result_2)
debug("succesCount", succesCount)
rank =
if succesCount >= 2
"成功"
elsif succesCount == 1
"部分的成功"
else
"失敗"
end
return "(1d100<=#{diff_1},#{diff_2}) > #{total}[#{result_1},#{result_2}] > #{rank}"
end
def getFullAutoResult(command)
return nil unless /^FAR\((-?\d+)(,(-?\d+))(,(-?\d+))(,(-?\d+))?\)/i =~ command
bullet_count = Regexp.last_match(1).to_i
diff = Regexp.last_match(3).to_i
broken_number = Regexp.last_match(5).to_i
bonus_dice_count = (Regexp.last_match(7) || 0).to_i
output = ""
# 射擊數不超過(8回*(PC技能値最大値/10))=72的上限
bullet_count_limit = 100
if bullet_count > bullet_count_limit
output += "\n彈藥太多。請改裝填#{bullet_count_limit}發。\n"
bullet_count = bullet_count_limit
end
return "正確裝填數。" if bullet_count <= 0
return "正確目標值。" if diff <= 0
if broken_number < 0
output += "\n正確故障值。排除獎勵記號。\n"
broken_number = broken_number.abs
end
unless @bonus_dice_range.include?(bonus_dice_count)
return "\n錯誤。獎勵、懲罰骰値為#{@bonus_dice_range.min}~#{@bonus_dice_range.max}です。"
end
output += "獎勵、懲罰骰値[#{bonus_dice_count}]"
output += rollFullAuto(bullet_count, diff, broken_number, bonus_dice_count)
return output
end
def rollFullAuto(bullet_count, diff, broken_number, dice_num)
output = ""
loopCount = 0
counts = {
hit_bullet: 0,
impale_bullet: 0,
bullet: bullet_count,
}
# 難度變更用Loop
4.times do |more_difficlty|
output += getNextDifficltyMessage(more_difficlty)
# ペナルティダイスを減らしながらロール用ループ削減獎勵骰時角色用Loop
while dice_num >= @bonus_dice_range.min
loopCount += 1
hit_result, total, total_list = getHitResultInfos(dice_num, diff, more_difficlty)
output += "\n#{loopCount}次: > #{total_list.join(', ')} > #{hit_result}"
if total >= broken_number
output += "卡彈"
return getHitResultText(output, counts)
end
hit_type = getHitType(more_difficlty, hit_result)
hit_bullet, impale_bullet, lost_bullet = getBulletResults(counts[:bullet], hit_type, diff)
counts[:hit_bullet] += hit_bullet
counts[:impale_bullet] += impale_bullet
counts[:bullet] -= lost_bullet
return getHitResultText(output, counts) if counts[:bullet] <= 0
dice_num -= 1
end
dice_num += 1
end
return getHitResultText(output, counts)
end
def getHitResultInfos(dice_num, diff, more_difficlty)
units_digit = rollPercentD10
total_list = getTotalLists(dice_num, units_digit)
total = getTotal(total_list, dice_num)
fumbleable = getFumbleable(more_difficlty)
hit_result = getCheckResultText(total, diff, fumbleable)
return hit_result, total, total_list
end
def getHitResultText(output, counts)
return "#{output}\n> #{counts[:hit_bullet]}發射擊命中、#{counts[:impale_bullet]}射擊貫穿、剩餘彈藥#{counts[:bullet]}發"
end
def getHitType(more_difficlty, hit_result)
successList, impaleBulletList = getSuccessListImpaleBulletList(more_difficlty)
return :hit if successList.include?(hit_result)
return :impale if impaleBulletList.include?(hit_result)
return ""
end
def getBulletResults(bullet_count, hit_type, diff)
bullet_set_count = getSetOfBullet(diff)
hit_bullet_count_base = getHitBulletCountBase(diff, bullet_set_count)
impale_bullet_count_base = (bullet_set_count / 2.to_f)
lost_bullet_count = 0
hit_bullet_count = 0
impale_bullet_count = 0
if !isLastBulletTurn(bullet_count, bullet_set_count)
case hit_type
when :hit
hit_bullet_count = hit_bullet_count_base # 正常命中彈藥數之計算
when :impale
hit_bullet_count = impale_bullet_count_base.floor
impale_bullet_count = impale_bullet_count_base.ceil # 貫穿彈藥數之計算
end
lost_bullet_count = bullet_set_count
else
case hit_type
when :hit
hit_bullet_count = getLastHitBulletCount(bullet_count)
when :impale
halfbull = bullet_count / 2.to_f
hit_bullet_count = halfbull.floor
impale_bullet_count = halfbull.ceil
end
lost_bullet_count = bullet_count
end
return hit_bullet_count, impale_bullet_count, lost_bullet_count
end
def getSuccessListImpaleBulletList(more_difficlty)
successList = []
impaleBulletList = []
case more_difficlty
when 0
successList = ["困難的成功", "通常成功"]
impaleBulletList = ["決定性的成功", "極限的成功"]
when 1
successList = ["困難的成功"]
impaleBulletList = ["決定性的成功", "極限的成功"]
when 2
successList = []
impaleBulletList = ["決定性的成功", "極限的成功"]
when 3
successList = ["決定性的成功"]
impaleBulletList = []
end
return successList, impaleBulletList
end
def getNextDifficltyMessage(more_difficlty)
case more_difficlty
when 1
return "\n 變更難度為困難的成功"
when 2
return "\n 變更難度為極限的成功"
when 3
return "\n 變更難度為決定性的成功"
end
return ""
end
def getSetOfBullet(diff)
bullet_set_count = diff / 10
if (diff >= 1) && (diff < 10)
bullet_set_count = 1 # 技能值9以下的最低限度保障處理
end
return bullet_set_count
end
def getHitBulletCountBase(diff, bullet_set_count)
hit_bullet_count_base = (bullet_set_count / 2)
if (diff >= 1) && (diff < 10)
hit_bullet_count_base = 1 # 技能值9以下的最低限度保障處理
end
return hit_bullet_count_base
end
def isLastBulletTurn(bullet_count, bullet_set_count)
((bullet_count - bullet_set_count) < 0)
end
def getLastHitBulletCount(bullet_count)
# 在剩餘彈藥為1的最低限度保障處理
if bullet_count == 1
return 1
end
count = (bullet_count / 2.to_f).floor
return count
end
def getFumbleable(more_difficlty)
# 成功判定時因只擲出49以下數值,而大失敗率上昇
return (more_difficlty >= 1)
end
end
end
end