Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RuneQuest:Roleplaying in Gloranthaのダイスボット作成 #637

Merged
merged 3 commits into from
Aug 6, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/bcdice/game_system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@
require "bcdice/game_system/RoleMaster"
require "bcdice/game_system/RuinBreakers"
require "bcdice/game_system/RuneQuest"
require "bcdice/game_system/RuneQuestRoleplayingInGlorantha"
require "bcdice/game_system/RyuTuber"
require "bcdice/game_system/Ryutama"
require "bcdice/game_system/SajinsenkiAGuS"
Expand Down
167 changes: 167 additions & 0 deletions lib/bcdice/game_system/RuneQuestRoleplayingInGlorantha.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# frozen_string_literal: true

module BCDice
module GameSystem
class RuneQuestRoleplayingInGlorantha < Base
# ゲームシステムの識別子
ID = 'RuneQuestRoleplayingInGlorantha'

# ゲームシステム名
NAME = 'RuneQuest:Roleplaying in Glorantha'

# ゲームシステム名の読みがな
SORT_KEY = 'るうんくえすと4'

# ダイスボットの使い方
HELP_MESSAGE = <<~MESSAGETEXT
・判定コマンド クリティカル、スペシャル、ファンブルを含めた判定を行う。
RQG<=成功率

例1:RQG<=80 (技能値80で判定)
例2:RQG<=80+20 (技能値100で判定)

・抵抗判定コマンド(能動-受動) クリティカル、スペシャル、ファンブルを含めた判定を行う。
RES(能動能力-受動能力)m増強値
増強値は省略可能。

例1:RES(9-11) (能動能力9 vs 受動能力11で判定)
例2:RES(9-11)m20 (能動能力9 vs 受動能力11、+20%の増強が能動側に入る判定)
例3:RES(9)m50 (能動能力と受動能力の差が9で、+50%の増強が能動側に入る判定)

・抵抗判定コマンド(能動側のみ) クリティカル、スペシャル、ファンブルは含めず判定を行う。
RSA(能動能力)m増強値
増強値は省略可能。

例1:RSA(9) (能動能力9で判定)
例2:RSA(9)m20 (能動能力9で判定、+20%の増強が能動側に入る判定)

MESSAGETEXT

register_prefix('RQG', 'RES', 'RSA')

def eval_game_system_specific_command(command)
case command
when /RQG/i
return do_ability_roll(command)
when /RES/i
return do_resistance_roll(command)
when /RSA/i
return do_resistance_active_characteristic_roll(command)
end
Result.nothing
Copy link
Member

@ysakasin ysakasin Aug 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Result.nothing が返されると汎用コマンドが動作しなくなってしまう可能性があるので、 nil を返すようにしてください。 Result.nothing は基本的にBase#result_2d6 などで使われることを想定しているもので、専用コマンドでは使わないほうが良いです。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらも了解しました。

end

private

# 技能などの一般判定
def do_ability_roll(command)
m = %r{\A(RQG)(<=([+-/*\d]+))?$}.match(command)
unless m
return Result.nothing
end

roll_value = @randomizer.roll_once(100)
unless m[3]
# RQGのみ指定された場合は1d100を振ったのと同じ挙動
return "(1D100) > #{roll_value}"
end

ability_value = Arithmetic.eval(m[3], :round)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:round でなく RoundType::ROUND を用いてください。もしくは、 #initialize@round_type を設定しておいて、 @round_type を参照するようにしてください。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

了解しました。

result_prefix_str = "(1D100<=#{ability_value}) >"

if ability_value == 0
# 0%は判定なしで失敗
return Result.failure("#{result_prefix_str} 失敗")
end

result_str = "#{result_prefix_str} #{roll_value} >"

# 判定
get_roll_result(result_str, ability_value, roll_value)
end

# 抵抗判定
def do_resistance_roll(command)
m = %r{\A(RES)([+-/*\d]+)(M([+-/*\d]+))?$}.match(command)
unless m
return Result.nothing
end

unless m[2]
return Result.nothing
end

difference_value = Arithmetic.eval(m[2], :round)
difference_value = -10 if difference_value < -10

resistance_velue = 50 + (difference_value * 5)
resistance_velue += Arithmetic.eval(m[4], :round) if m[4]

roll_value = @randomizer.roll_once(100)
result_str = "(1D100<=#{resistance_velue}) > #{roll_value} >"

# 判定
get_roll_result(result_str, resistance_velue, roll_value)
end

# 能動側のみの対抗判定
def do_resistance_active_characteristic_roll(command)
m = %r{\A(RSA)(\d+)(M([+-/*\d]+))?$}.match(command)
unless m
return Result.nothing
end

unless m[2]
return Result.nothing
end

active_ability_value = m[2].to_i
if active_ability_value == 0
return "0は指定できません。"
end

modifiy_value = m[4] ? Arithmetic.eval(m[4], :round) : 0
roll_value = @randomizer.roll_once(100)
active_value = active_ability_value * 5 + modifiy_value
result_prefix_str = "(1D100<=#{active_value}) > #{roll_value} >"

note_str = "クリティカル/スペシャル、ファンブルは未処理。必要なら確認すること。"

if roll_value >= 96
# 96-99は無条件で失敗
Result.failure("#{result_prefix_str} 失敗\n#{note_str}")
elsif roll_value <= 5 || roll_value <= modifiy_value
# 02-05あるいは修正値以下は無条件で成功
Result.success("#{result_prefix_str} 成功\n#{note_str}")
else
# 上記全てが当てはまらない時に突破可能な能力値を算出
"#{result_prefix_str} 相手側能力値#{active_ability_value + (50 + modifiy_value - roll_value) / 5}まで成功\n#{note_str}"
end
end

# 判定結果の取得
def get_roll_result(result_str, success_value, roll_value)
critical_value = (success_value.to_f / 20).round
special_value = (success_value.to_f / 5).round
funmble_value = ((100 - success_value.to_f) / 20).round
ysakasin marked this conversation as resolved.
Show resolved Hide resolved

if (roll_value == 1) || (roll_value <= critical_value)
# クリティカル(01は必ずクリティカル)
Result.critical("#{result_str} クリティカル/スペシャル")
elsif (roll_value == 100) || (roll_value >= (100 - funmble_value + 1))
# ファンブル(00は必ずファンブル)
Result.fumble("#{result_str} ファンブル")
elsif roll_value <= special_value
# スペシャル
Result.success("#{result_str} スペシャル")
elsif (roll_value <= 95) && ((roll_value <= 5) || (roll_value <= success_value))
# 成功(02-05は必ず成功で、96-99は必ず失敗)
Result.success("#{result_str} 成功")
else
# 失敗
Result.failure("#{result_str} 失敗")
end
end
end
end
end
Loading