ウマサポLua設定集【初級・中級編】
[お知らせ]
しばらくヒカセンとエルデンに時間を割いていたのですが、新シナリオ投入されたので最近戻ってきました。休んでいた間にいろいろ状況が変わっていたので※、またいちからスクリプト整理しなおしています。こちらの記事は情報が古くなっており、本文が見えないと紛らわしいので無料化しました。ロジックを参考にする程度に留めていただければと思います。
※ウマサポの仕様とかサポカイベントの仕様とか
[このエントリの目的]
自分ならこういうプレイングをするというアイディアと設定.luaへの実装例を書いていきます。そのうち体系的に整理したい。
[今あるコンテンツ]
【初級】
・固定イベントのステータスボーナスを考慮してトレーニング優先度を制御
・シニアの正月明け(1月前半)では賢さ練習をしない
・育成キャラごとに取得するスキルのタイプを設定したい
・固有継承スキルは取りたくない
・たづなの絆ゲージを早い段階で緑にしておきたい
【中級】
・自作スクリプトを設定.luaの外で管理したい
・スキル習得やヒント獲得状況に合わせてヒントを踏むか制御したい
・目標値に近づく程トレーニングの評価点を下方補正したい
・強制出走レースのリストをcsvで管理したい(8/29修正)
・チャンピオンズミーティングの条件別にスキルの取得優先度をまとめて変更したい(10/3追加)
・地固め習得を効率よく回したい
・SS2B育成か4B育成を判定してそれぞれに合う育成をしたい(11/5追加)
【初級】
数行のコードを追加・変更するレベル
目標ステータスを超えたら関連するトレーニングの優先度を下げる
【背景】例えば4B育成する際にスピードがここまで上がったら後は一切スピード練習しないレベルで避けたい
【実装先】getStatusScore関数
function getStatusScore( statusName, trainingName, hp, failureRate )
(中略)
-- 実質的に超えたいステータス
local goal_speed = 600
-- URA決勝~育成終了までに貰えるステータスボーナス
local lastBonus = 30
-- 設定用ステータス
local target_speed = goal_speed - lastBonus
(中略)
-- 目標値を超えたら優先度を下方補正
if g_status[STATUS.SPEED] > target_speed and statusName == STATUS.SPEED then score = score * 0.01 end
return score
end
シニアの正月明け(1月前半)では賢さ練習をしない
【背景】直後に福引イベントで高確率で体力回復が発生するため、賢さトレーニングをすると体力が溢れがち
【実装先】getStatusScore関数
function getStatusScore( statusName, trainingName, hp, failureRate )
(中略)
-- 3年目の正月明けの練習は直後に回復イベントが来るので賢さは選ばないようにする
if g_status[STATUS.SEASON].index == SEASON.SENIOR_1A.index then
if trainingName == STATUS.INT then score = -10000 end
end
return score
end
育成キャラごとに取得するスキルのタイプを設定したい
【背景】育成キャラの限定タイプ習得スキル設定しても機能してなくない?
※v0.07で限定タイプ習得スキル設定に逃げ/先行/差し/追込が追加されましたが、設定:デフォルト.luaの関連個所が更新されていないのでそのままでは機能しません。
【実装先】getSkillScore関数
function getSkillScore( skillInfo, hintLevel )
(中略)
-- 限定タイプ習得スキル設定の逃げ・先行・差し・追込の各脚質優先度のスコアから最大値を設定
local t1 = skillInfo.stylePriority[STYLE.NIGE]
local t2 = skillInfo.stylePriority[STYLE.SENKOU]
local t3 = skillInfo.stylePriority[STYLE.SASHI]
local t4 = skillInfo.stylePriority[STYLE.OIKOMI]
local score = math.max(t1, t2, t3, t4)
(中略)
-- 限定タイプスキルの場合
-- INDEFINITEは"-"でなにも設定されていない
if skillInfo.limitedType ~= INDEFINITE then
-- 限定タイプ習得スキルに設定されている場合
if characterInfo.limitedTypeSkill[skillInfo.limitedType] then
-- スコアをそのまま使用
-- 限定タイプ習得スキルに設定されていない場合
else
-- スコアを0にする
score = 0
end
end
return score
end
固有継承スキルは取りたくない
【背景】継承用ウマ娘には固有継承とっても意味がないし、ウマサポ上で固有スキルの優先度をポチポチ0にしていくのめんどくさい
【実装先】getSkillScore関数
function getSkillScore( skillInfo, hintLevel )
(中略)
-- 固有スキルは習得しない
if skillInfo.rare == "固有" then
score = -1 -- -1にしておけば他に取るスキルが無くなった時にスコア0を優先する
end
(中略)
return score
end
たづなの絆ゲージを早い段階で緑にしておきたい
【背景】ジュニアの内におでかけ発生させるために8月くらいまではたづなの優先度を上げてトレーニングしたい
【実装先】getKizunaScore関数
※ウマサポのバージョンアップで友人用の変数が増えたので今後合わせて更新予定。ひとまず↓のままでも使用可能です。かっしーの分はたづなさんのところを複製してください。
function getKizunaScore( charaName, hintFlag )
(中略)
-- 友人タイプの場合
elseif supportChara.type == SUPPORT_TYPE.FRIEND then
-- たづな用調整
if charaName == "駿川たづな" then
-- 1年目8月までにLv3(緑)を目指す
if g_status[STATUS.SEASON].index < SEASON.JUNIOR_8B.index then
if supportChara.kizunaLevel < 3 then
score = score * 15
end
else
-- 1年目8月過ぎても達成できていなかったら全力
if supportChara.kizunaLevel < 3 then
score = score * 100
end
end
end
end
(中略)
return score, hintScore
end
【中級】
自分で関数を作ってより細かい制御をする
自作スクリプトを設定.luaの外で管理したい
※ここらへんからスクリプトの行数が増えるので、ファイルを分けることをお勧めします。(9/1追記)
[設定.lua]
require "myScript"
----------------------------------------------------------------------------------------------------
-- 基本設定
----------------------------------------------------------------------------------------------------
(中略)
このように設定.luaの冒頭に require "[Filename]"と記述すると、ウマサポと同じフォルダの中にある"[Filename].lua"をロードします。
[myScript.lua]
----------------------------------------------------------------------------------------------------
-- グローバル変数の定義
----------------------------------------------------------------------------------------------------
-- URA決勝~育成終了までに貰えるステータスボーナス
lastBonus = 25
(中略)
----------------------------------------------------------------------------------------------------
-- calcVaildHintscore関数
-- サポートカード別に取得したいスキルの習得・ヒント獲得状況に応じてヒントスコアを補正する
----------------------------------------------------------------------------------------------------
-- 引数:referSupport
-- サポートカード名(e.g. アイネスフウジン [飛び出せ、キラメケ])
-- 引数:targetSkills
-- 取得したいスキル名のリスト
-- ※スキル名はミス防止のためスキル:デフォルト.csvからコピペすること
-- 戻り値
-- 補正したヒントスコア
----------------------------------------------------------------------------------------------------
function calcVaildHintscore(supportChara, referSupport, targetSkills)
local hintScore = 0
(中略)
グローバル変数や関数を定義しておくと、設定.luaでも同じように呼び出すことができます。
【注意点】
・ファイル名には全角文字を入れない方がいいかも
・自作luaファイルを作って保存する際は文字コードをUTF-8で保存すること
(9/1追記)
ウマサポのバージョンが上がるごとに自作スクリプトを移動するのがめんどくさい場合は別途それ用のフォルダを切っておき、設定.luaでそちらを参照するようにするとよいです。(それでも設定.luaをはじめとするウマサポ由来の設定ファイルは手動移動する必要がありますが)
[設定.lua]
-- いわゆる環境変数PATHを通す処理
package.path = package.path .. ";C:\\Umamusume\\UmasapoExtLibrary\\?.lua"
これを設定.luaの冒頭に記述してからrequireすれば追加したパスへrequire指定されたファイルを検索しに行きます。バックスラッシュはLuaではエスケープ文字なので、2つ重ねる必要があります。
\\?.luaの部分がなければcsvも探しに行ってくれるのでは?と期待したのですが駄目だったので、ファイル指定をするところで相対パスを指定しています。
-- CSVファイルを相対パスで指定(.でカレントディレクトリ、..でカレントディレクトリの1つ上の階層)
-- ※ここで言うカレントディレクトリはウマサポの実行ファイルがあるディレクトリ
-- この例ではウマサポが入っているフォルダの上に「UmasapoExtLibrary」フォルダを作成して、その中ある「racePlanning.csv」を参照
raceplanningAlias, list = setRacePlanning('..\\UmasapoExtLibrary\\racePlanning.csv')
スキル習得やヒント獲得状況に合わせてヒントを踏むか制御したい
【背景】例えばSRキングヘイローから良バ場○とコーナー回復〇だけ貰ったら他のスキルは不要なので、以後はヒントアイコンが発生していてもトレーニングの優先度計算にヒントスコアを含めないようにしたい
【実装先】getKizunaScore関数とgetSkillScore関数
行数が多くなるので自分で関数を定義して呼び出します。
----------------------------------------------------------------------------------------------------
-- calcVaildHintscore関数
-- サポートカード別に取得したいスキルの習得・ヒント獲得状況に応じてヒントスコアを補正する
----------------------------------------------------------------------------------------------------
-- 引数:referSupport
-- サポートカード名(e.g. アイネスフウジン [飛び出せ、キラメケ])
-- 引数:targetSkills
-- 取得したいスキル名のリスト
-- ※スキル名はミス防止のためスキル:デフォルト.csvからコピペすること
-- 戻り値
-- 補正したヒントスコア
----------------------------------------------------------------------------------------------------
function calcVaildHintscore(referSupport, targetSkills)
local hintScore = 0
-- 因子化したいスキルの数を設定
local hopeSkillNum = #targetSkills
local gotHintNum = 0
for i = 1, hopeSkillNum do
local gotFlg = 0
-- チェックするスキルを習得済みなら+1
if #g_status[STATUS.ACQUIRE_SKILL] > 0 then
for j = 1, #g_status[STATUS.ACQUIRE_SKILL] do
if g_status[STATUS.ACQUIRE_SKILL][j].name == targetSkills[i] then
gotFlg = 1
break
end
end
end
-- ヒントLvがg_skillInfoに追加済みの場合
if isKeyExist(g_skillInfo[targetSkills[i]], "hintLevel") then
-- チェックするスキルを習得していない場合、ヒントLvが1以上ならヒント獲得フラグを立てる
if gotFlg == 0 and g_skillInfo[targetSkills[i]].hintLevel > 0 then gotFlg = 1 end
-- ヒントLvがg_skillInfoに追加されていない場合(デビュー戦前・一度スクリプトを止めてから再度実行時)
else
-- ヒントを得ていないものとして扱う
-- 何もしない
end
gotHintNum = gotHintNum + gotFlg
end
-- 該当のサポカで欲しいスキルのヒントを取り切れていなかったらヒントを踏む
if gotHintNum < hopeSkillNum then
-- サポートキャラクターのデータベースに登録しているヒントマークの優先度をスコアにする
hintScore = g_supportCharacterInfo[referSupport].hintPriority
end
if hintScore > 0 then print("(!)" .. removeNickName(referSupport) .. "は有効なヒント") end
return hintScore
end
----------------------------------------------------------------------------------------------------
-- isKeyExist関数
-- 対象のテーブルのキーに指定のkeyが存在するかどうかチェックする
----------------------------------------------------------------------------------------------------
-- 引数:tbl
-- チェックするテーブル
-- 引数:key
-- 確認するkeyの名前(文字列指定)
-- 戻り値
-- 存在すればTrue、なければFalseを返す
----------------------------------------------------------------------------------------------------
function isKeyExist( tbl, key )
for k, v in pairs(tbl) do
if k == key then return true end
end
return false
end
そしたらgetKizunaScore関数内の「if hintFlag then~」の中で狙いを絞りたいスキルを指定します。
SSRキタサンブラックでコーナー回復〇、逃げ直線〇に狙いを絞る場合
function getKizunaScore( charaName, hintFlag )
(中略)
-- ヒントマーク(!)によるスコアの算出
local hintScore = 0
if hintFlag then
-- 取得済みスキルとヒントLvを参照して必要なヒントのみ優先する
-- ヒントLvはgetSkillScoreでg_skillInfoにhintLevelをkey追加して初めて参照できるため、以下の条件では参照できない
-- ①デビュー戦前、②スクリプトを停止してから再実行してからスキル習得画面を開くまで
-- ①、②の場合とも、欲しいヒントを得ていない前提で処理する
-- 【注意】○や◎は手打ちせずに、データシートからコピペすること
-- いずれチャンミ設定をリストか何かで引数にしてそれに対するアウトプットみたいなことをやりたい
-- スピード
if charaName == "キタサンブラック" then
hintScore = calcVaildHintscore("キタサンブラック [迫る熱に押されて]", {"コーナー回復○", "逃げ直線○"})
end
end
(中略)
return score, hintScore
end
但しg_skillInfoにはヒントLvを格納する列がないため、このままでは習得したスキルの考慮はできてもヒントの考慮ができません。そこでhintLevelを引数で受けるgetSkillScore関数の中でg_skillInfoにhintLevelのKeyを追加します。
function getSkillScore( skillInfo, hintLevel )
(中略)
-- ヒントLvを格納
g_skillInfo[skillInfo.name].hintLevel = hintLevel
(中略)
return score
end
g_skillInfoはグローバルテーブルなのでどこからでもアクセスできますが、getSkillScore関数はスキルを習得するタイミングでのみ呼び出されるため、ヒントLvを参照できるようになるのは出走レース前にスキルを習得しにいくタイミング以降になります。従って以下の制約があります。
①デビュー戦前までは機能しない、isCheckAcquireSkill関数でチェックタイミングをある程度頻繁に行うようにする必要がある
②g_skillInfoはスクリプト開始時にスキル.csvとスキル:デフォルト.csvからロードして作成されるテーブルであるため、一度スクリプトを停止すると再びスキル習得モードに入るまではヒントLvを参照できなくなる。
※Luaはファイルの書き込みをするioモジュールがあるのですがコンパイルされていない?ためか今の所使えない。
→v0.09でioモジュールが組み込まれたので可能になりました。いずれ更新
目標値に近づく程トレーニングの評価点を下方補正したい
【背景】4B育成を狙う際に平均的にステータスを伸ばしたいが、サポカ編成の偏りによってはバランス良く伸ばせずにB未満になってしまう場合がある
【実装先】getStatusScore関数
ステータスが目標値に近づくほど、スコアが低く補正されるようにする関数を作ります。
----------------------------------------------------------------------------------------------------
-- softAdjust関数
-- 三角比的に目標値近辺に近づくほど下方補正がかかる係数でスコアを補正する
----------------------------------------------------------------------------------------------------
-- 引数:inScore
-- 補正前のスコア
-- 引数:statusName
-- 対象のステータス
-- 引数:target_parms
-- 実質目標ステータスのリスト
-- 戻り値
-- 補正したスコアを返す
----------------------------------------------------------------------------------------------------
-- 目標値に近づくほどスコアの優先度を下げる
function softAdjust(inScore, statusName, target_parms)
for i = 1,#status_tbl do
if statusName == status_tbl[i] then
-- 目標値に対する現在値の達成度
local progress = g_status[statusName] / target_parms[i]
-- 達成度が1未満の時はこれをcosθとみなし、補正係数をsinθで算出してスコアに適用する
if progress < 1 then
return math.ceil(inScore * math.sqrt(1 - (progress * progress)))
-- 達成度が1以上の時は、0.01に補正(できるだけ高いパラメータを選択するため)
else
return math.ceil(inScore * 0.01)
end
end
end
end
----------------------------------------------------------------------------------------------------
-- isValExist関数
-- 対象のリストに指定の要素が存在するかどうかチェックする
----------------------------------------------------------------------------------------------------
-- 引数:list
-- チェックするリスト
-- 引数:val
-- 確認するkeyの名前(文字列指定)
-- 戻り値
-- 存在すればTrue、なければFalseを返す
----------------------------------------------------------------------------------------------------
function isValExist( list, val )
for i = 1, #list do
if list[i] == val then return true end
end
return false
end
とりあえず、現在値が目標値よりも遠いときは緩やかに、近づくほど強く補正を受けることを表現するものとして三角比を選びました(適当)
getStatusScore関数の中ではこのように呼び出します。
function getStatusScore( statusName, trainingName, hp, failureRate )
(中略)
-- 0から100までの範囲内に収める
if score > 100 then
score = 100
elseif score < 0 then
score = 0
end
end
-- メインステータスならスコア補正をする
local target_tbl = {600,600,600,300,600}
local tbl = { STATUS.SPEED, STATUS.STAMINA, STATUS.POWER, STATUS.GUTS, STATUS.INT }
if isValExist(tbl , statusName) then
score = softAdjust(score, statusName, target_tbl)
end
return score
end
target_tbl = {600,600,600,300,600}はスピ・スタ・パワ・根性・賢さの目標値のテーブルです。説明の簡略化のためにローカル定義していますが、実際は設定.luaの冒頭でグローバル変数で定義して使う方が便利です。
※わざわざテーブルを作ってステータスを指定しているのは、getStatusScore関数はトレーニングで得られるスキルポイントの評価計算にも使われているため、これを避けるためです。
強制出走レースのリストをcsvで管理したい(8/29修正)
【背景】因子用の育成で重賞ボーナスを狙う場合、G2/G3まで含めると追加出走レースだけで20近く記述しないといけません。キャラごとにいちいち手打ちしたり、管理するのが面倒なのでキャラ別の出走レースリストをcsvで管理して楽したい。
【実装先】自作関数
v0.09で追加されたioモジュールを使ってcsvファイルを読み込み、強制出走レースの配列に格納していくだけです。
csvファイルはExcelで重賞ボーナスを調整しながら作ったカレンダーからワンクリックで吐き出せるようにしたもので、以下のような中身になっています。
----------------------------------------------------------------------------------------------------
-- setRacePlanning関数
-- 強制出走レースをcsvファイルから参照して設定する
----------------------------------------------------------------------------------------------------
-- 引数:filename
-- 参照するcsvファイル
-- 戻り値
-- csvファイルのコメント
----------------------------------------------------------------------------------------------------
function setRacePlanning(filename)
local ret = ''
local f = io.open(filename, 'r')
local j = 1 -- 読込行数
for line in f:lines() do
local data = split(line, ",")
-- 1行目はコメント用
if j == 1 then
-- 戻り値
ret = data[2]
end
if j > 1 then
CONFIG.RUN_RACE[j - 1] = { name = data[1] , season = SEASON[data[2]] }
end
j = j + 1
end
f:close()
return ret
end
----------------------------------------------------------------------------------------------------
-- split関数
-- 文字列を指定のデリミタで分割したリストを作成する
----------------------------------------------------------------------------------------------------
-- 引数:str
-- 対象文字列
-- 引数:delim
-- 区切り文字列
-- 戻り値
-- デリミタがなければ元の文字列を、あれば分割してテーブル(リスト)を返す
----------------------------------------------------------------------------------------------------
function split(str, delim)
-- Eliminate bad cases...
if string.find(str, delim) == nil then
print('no delimitor:' .. str)
return { str }
end
local t = {}
i=1
for s in string.gmatch(str, "([^"..delim.."]+)") do
t[i] = s
i = i + 1
end
return t
end
これを設定.luaで呼びだして、戻り値をonStartTraining関数でprintすれば育成開始時に何の設定をしたかが可視化されます。
--------------------------------------------------------------------------------------
-- 強制出走レース
--------------------------------------------------------------------------------------
raceplanningAlias = setRacePlanning('racePlanning.csv')
----------------------------------------------------------------------------------------------------
-- onStartTraining関数
-- 育成開始時に呼び出される
-- 呼び出されるタイミングは実行開始後onStartTurn関数が呼び出される直前で1回のみ呼び出される
-- ステータス等は認識されている状態になっている
-- 初期化処理等を記述したい場合に利用する
----------------------------------------------------------------------------------------------------
function onStartTraining()
-- ■ 出走レースプラン:中距離逃げ因子用ブルボン と上記例のcsvを使うと表示される
print("■ 出走レースプラン:" .. raceplanningAlias)
end
参考までにExcelのマクロ。こちらのツールも綺麗化できたらご紹介したいですね。
Sub createRacePlanTable()
'出走レーステーブル作成シート
Dim c As Worksheet
Set c = ThisWorkbook.Worksheets("出走レーステーブル作成")
'Umamusume Trainer's Clipboard(UTCと略称)を使用して出走カレンダーを作成しているため、
'UTCにおけるレース名表記とウマサポのテーブルの表記を紐づけるための読替表を間に入れています
'出走レーステーブル名読替表
Dim tr As Worksheet
Set tr = ThisWorkbook.Worksheets("レース名読替")
'読込対象の情報セット
'対象シート
Dim t As Worksheet
Set t = ThisWorkbook.Worksheets(c.Range("C2").Value)
'年度の列・行範囲
Dim y_col, t_col, char As Long
Dim row_s, row_e As Long
Dim comment As String
With c
y_col = Range("D3")
t_col = Range("D4")
row_s = Range("C5")
row_e = Range("C6")
char = Range("D7")
comment = Range("C8")
End With
'ウマサポの強制出走レースに設定するシーズンとレース名の配列を作成
Dim season_arr(), race_arr() As String
Dim racename_clip, racename_umasapo As String
Dim season, year, turn As String
Dim race_count As Long '出走レース数
race_count = 0
Dim i As Long
For i = row_s To row_e
'一応初期化
racename_clip = ""
racename_umasapo = ""
season = ""
year = ""
turn = ""
If t.Cells(i, char) <> "" Then
race_count = race_count + 1
'レース名をUmamusume Trainer's Clipboardの表記からウマサポのテーブルの表記に読み替えて配列に格納
racename_clip = t.Cells(i, char)
racename_umasapo = WorksheetFunction.VLookup(racename_clip, tr.Range("A:B"), 2, False)
ReDim Preserve race_arr(race_count)
race_arr(race_count - 1) = racename_umasapo
'時期をウマサポのseason用のフォーマットで作成して配列に格納
year = t.Cells(i, y_col)
Select Case year
Case "ジュニア"
year = "JUNIOR"
Case "クラシック"
year = "CLASSIC"
Case "シニア"
year = "SENIOR"
End Select
turn = t.Cells(i, t_col)
season = year & "_" & turn
ReDim Preserve season_arr(race_count)
season_arr(race_count - 1) = season
End If
Next i
'csvに出力
'出力ファイル名
Dim racePlanTable As String
Const FILENAME As String = "racePlanning.csv"
'ストリーム、最終行番号
Dim outStream As New ADODB.Stream
'ストリーム準備
Dim j As Long
Dim line As String
With outStream
.Type = adTypeText
.Charset = "UTF-8"
.LineSeparator = adCRLF
.Open
End With
'全レコードへの処理
For i = 1 To UBound(race_arr) + 1
'1行目はコメント用
If i = 1 Then
line = "コメント," & comment
'2行目以降にテーブル本体
Else
line = race_arr(i - 2) & "," & season_arr(i - 2)
End If
'i行目のレコードをoutStreamに出力
outStream.WriteText line, adWriteLine
Next i
'出力CSV保存
outStream.SaveToFile ThisWorkbook.Path & "\" & FILENAME, adSaveCreateOverWrite
'後処理
outStream.Close
Set outStream = Nothing
MsgBox "出力完了!", vbOKOnly + vbInformation, "強制出走レーステーブル作成処理"
End Sub
※8/29修正内容
SEASONが単なる添え字と勘違いしてSEASON.JUNIOR_8Bを単なる変数値か何かと思ってました。実際のところSEASONはテーブルで、
SEASON.JUNIOR_8B = {name = "ジュニア級8月後半", index = 16, race1? = "クローバー賞", ... race20? = "" }}
という構造のテーブルになっています。(race1?のkey名は未確認)
なので、csvの方はJUNIOR_8Bの部分だけにして、これをSEASONに渡すことでちゃんとテーブルをseasonに渡すようにしたら上手くいきました。
チャンピオンズミーティングの条件別にスキルの取得優先度をまとめて変更したい
【背景】チャンミの条件ごとに緑スキルや特攻スキルの取得優先度をウマサポの画面でチマチマ変えるのめんどくさい
【実装先】自作関数
強制出走レース設定の二番煎じ。とりあえず作った感ある雑さですがせっかくなので載せておきます
こんな感じのマクロでまずcsvをこさえます
----------------------------------------------------------------------------------------------------
-- setRaseSpecificSkillPriority関数
-- チャンミの条件別のスキル優先度設定をcsvファイルから参照して設定する
----------------------------------------------------------------------------------------------------
-- 引数:filename
-- 参照するcsvファイル
-- 戻り値
-- csvファイルのコメント
-- ※デフォルトcsvのロード→ユーザー設定csvのロード→この関数の設定をロードの順にテーブルを上書きする
----------------------------------------------------------------------------------------------------
function setRaseSpecificSkillPriority(filename)
local ret = ''
local list = {}
local f = io.open(filename, 'r')
local j = 1 -- 読込行数
for line in f:lines() do
-- 1行目はコメント用
if j == 1 then
-- 戻り値
ret = line
end
if j > 1 then
g_skillInfo[line].stylePriority[STYLE.NIGE] = 1000
g_skillInfo[line].stylePriority[STYLE.SENKOU] = 1000
g_skillInfo[line].stylePriority[STYLE.SASHI] = 1000
g_skillInfo[line].stylePriority[STYLE.OIKOMI] = 1000
end
j = j + 1
end
f:close()
return ret
end
これをonStartTrainingで実行します
function onStartTraining()
specificSkillAilias = setRaseSpecificSkillPriority('raceSpecificSkills.csv')
print("■ 目標チャンピオンズミーティング:" .. specificSkillAilias)
end
予めこの関数の対象になるスキルの優先度はウマサポの設定で全部0にしておいてください。
地固め習得を効率よく回したい
【背景】地固め因子を狙っていくときにSRエアグルーヴを編成してできるだけ手動で育成するときと同じような動きを再現したい。
例えば個人的には以下のような動きをしています。
①SRエアグルーヴのヒントを最優先にする※1,※2
②SRエアグルーヴから地固めを貰う確率を上げるために彼女から貰える他のスキルを最優先で習得する
※1.予めウマサポでサポートキャラクター一覧のヒント優先度を高くしておくか、上記で紹介しているcalcVaildHintscore関数のスコアの部分に係数を掛けるなりすればOK。
※2.強制出走レースは重賞ボーナス狙いのためエアグルーヴのヒントがあってもレースを優先しています
【実装先】getKizunaScore関数、getSkillScore関数
その内モジュール化しようかなと思いつつ現状やりたいのが地固めとSRエアグルーヴだけなのでハードコーディングしちゃってます。
まずエアグルーヴのヒントを踏むかどうかは上記で紹介したcalcVaildHintscore関数を使います。
挙動を説明すると以下の場合、地固めを習得済みかヒントを得ている場合はエアグルーヴのヒントを無視します。
function getKizunaScore( charaName, hintFlag , trainingInfo )
(中略)
-- ヒントマーク(!)によるスコアの算出
local hintScore = 0
if hintFlag then
(中略)
if charaName == "エアグルーヴ" then hintScore = calcVaildHintscore("エアグルーヴ [副会長の一刺し]", {"地固め"}) end
end
(中略)
return score, hintScore
end
更にヒントを踏んだ際に予め地固め以外のスキルを埋めておくため、地固めを習得するかヒントを得るまでは他のスキルを優先的に習得していきます。
function getSkillScore( skillInfo, hintLevel )
(中略)
-- 一時的な記述(とりあえずの需要が地固めしかないので)
-- 地固めを未習得またはヒント未獲得ならそれ以外のスキルの習得優先度を10倍にする
local zigatame = 0 -- 地固め習得orヒント獲得フラグ
if #g_status[STATUS.ACQUIRE_SKILL] > 0 then
for i = 1, #g_status[STATUS.ACQUIRE_SKILL] do
if g_status[STATUS.ACQUIRE_SKILL][i].name == "地固め" then
zigatame = 1
break
end
end
end
-- 地固めのヒントを獲得しているかどうか
if g_skillInfo["地固め"].hintLevel then zigatame = 1 end
-- SRエアグルーヴに練習で貰える地固め以外のヒント一覧を定義
local airgrooveHints = {"中距離直線○", "中距離直線◎", "追込ためらい", "追込焦り", "テンポアップ", "ペースキープ"}
for i = 1, #airgrooveHints do
-- 地固めを獲得していないなら、SRエアグルーヴの他のヒントの習得優先度を10倍にする
if zigatame == 0 then
if skillInfo.name == airgrooveHints[i] then score = score * 10 end
elseif zigatame == 1 then
if skillInfo.name == airgrooveHints[i] then score = score end
end
end
return score
end
改良点としてはエアグルーヴのヒントは来たのに体力不十分で踏みに行けないシチュを避けるために通常時は体力温存しつつ、エアグルーヴのヒントだけはある程度の失敗率を許容して踏みに行くようにすることでしょうか。getActionあたりに仕込めばできそう。
SS2B育成か4B育成を判定してそれぞれに合う育成をしたい
最近全然更新できてないので普段使ってる設定でまだ記事化してないものを追加
【背景】SS2B育成と4B育成はステの盛り方が異なるので、目標値から判定してそれぞれの育成モードに分けてトレーニング評価を設定したい
【実装先】getStatusScore関数
やってることとしては、
①目標値に1100以上が設定されていればSSと判断して評価モードを分岐
②4Bでは基本デフォルト通り
③SSの場合は育成序盤にSS目標パラメータの目標値を低めに再設定することで、序盤のステの偏りを防いでいます。特にスピードが低すぎて出走レースで負けやすくなってしまう問題への対応です。
----------------------------------------------------------------------------------------------------
-- 事前設定
-- ウマサポのUIで設定する目標値とは別にこの値さえ超えていればいい、というパラメータを設定しておく
-- goal_xxxx ⇒ 各パラメータの必須目標
-- lastBonus ⇒ 最後のトレーニング以降に自動的に見込める値(URA決勝+シナリオ+友人等)
----------------------------------------------------------------------------------------------------
lastBonus = 30
-- SS2B育成の例
goal_speed = 600
goal_stamina = 1100
goal_power = 600
goal_guts = 300
goal_int = 300
-- 4B育成の例
goal_speed = 600
goal_stamina = 600
goal_power = 600
goal_guts = 300
goal_int = 600
-- 最後のトレーニング+URA決勝後のボーナス分で目標値になっていればよい
target_speed = goal_speed - lastBonus
target_stamina = goal_stamina - lastBonus
target_power = goal_power - lastBonus
target_guts = goal_guts - lastBonus
target_int = goal_int - lastBonus
----------------------------------------------------------------------------------------------------
-- getStatusScore関数
-- ステータスによるスコアの算出をする
-- トレーニングとイベント選択肢でのステータス上昇によるスコア算出時に呼び出される
----------------------------------------------------------------------------------------------------
function getStatusScore( statusName, trainingInfo )
local score = 0
-- キャラクター情報を保持
local characterInfo = g_characterInfo[g_status[STATUS.NAME]]
-- 体力の場合
if statusName == STATUS.HP then
-- スコアの設定の体力で設定している値
score = SCORE.HP
-- 最大体力の場合
elseif statusName == STATUS.MAXHP then
-- スコアの設定の最大体力で設定している値
score = SCORE.MAXHP
-- やる気の場合
elseif statusName == STATUS.MOTIVATION then
-- スコアの設定のやる気で設定している値
score = SCORE.MOTIVATION
-- スキルポイントの場合
elseif statusName == STATUS.SKILLPT then
-- スコアの設定のスキルポイントで設定している値
score = SCORE.SKILLPT
-- 優先度によるスコア補正
local statusPriority = characterInfo.statusPriority[statusName]
score = score * statusPriority / 100
-- それ以外(メインステータス)の場合
else
-- 賢さの目標値を高めにしておく場合、序盤から賢さを踏み過ぎてスピスタパワが通常より低くなりやすくなるため事故率が上がる
-- 賢さは最後に帳尻が合えばいいので、URAファイナルまでは目標値を下げる
if g_status[STATUS.SEASON].index < SEASON.JUNIOR_12B.index then
if target_int > 300 then
characterInfo.statusTarget[STATUS.INT] = target_int - 150
else
characterInfo.statusTarget[STATUS.INT] = 250
end
elseif g_status[STATUS.SEASON].index < SEASON.CLASSIC_12B.index then
characterInfo.statusTarget[STATUS.INT] = target_int
elseif g_status[STATUS.SEASON].index < SEASON.SENIOR_12B.index then
characterInfo.statusTarget[STATUS.INT] = target_int + 50
end
-- 根性も同様
if g_status[STATUS.SEASON].index < SEASON.JUNIOR_12B.index then
if target_guts > 300 then
characterInfo.statusTarget[STATUS.GUTS] = target_guts - 300
else
characterInfo.statusTarget[STATUS.GUTS] = 200
end
elseif g_status[STATUS.SEASON].index < SEASON.CLASSIC_12B.index then
characterInfo.statusTarget[STATUS.GUTS] = target_guts - 100
elseif g_status[STATUS.SEASON].index < SEASON.SENIOR_12B.index then
characterInfo.statusTarget[STATUS.GUTS] = target_guts - 20
end
-- 因子育成でSSを狙う場合
if math.max(goal_speed, goal_stamina, goal_power, goal_guts, goal_int) >= 1100 then
-- SSを狙うパラメータ(念のため複数ある場合の優先度は パワー>スタミナ>賢さ>根性>スピード)
local SSparam
if goal_speed >= 1100 then SSparam = STATUS.SPEED end
if goal_guts >= 1100 then SSparam = STATUS.GUTS end
if goal_int >= 1100 then SSparam = STATUS.INT end
if goal_stamina >= 1100 then SSparam = STATUS.STAMINA end
if goal_power >= 1100 then SSparam = STATUS.POWER end
if statusName == SSparam then
controlmode = SSparam .. "SS育成"
if g_status[STATUS.SPEED] < 400 then
-- 一時的にSS狙いパラメータの目標値を400に制限する
score = (400 - g_status[statusName]) / 10
elseif g_status[STATUS.SPEED] < 500 then
-- 一時的にSS狙いパラメータの目標値を700に制限する
score = (700 - g_status[statusName]) / 10
else
-- 規定値を超えたら狙いの値になるまでは評価1.0倍、超えたら0
-- ステータスの目標値から現在値を引いて10で割った値をスコアにする
score = (characterInfo.statusTarget[statusName] - g_status[statusName]) / 10
if g_status[statusName] >= 1100 - lastBonus then
score = 0
else
score = score * 1.0
end
end
else
score = (characterInfo.statusTarget[statusName] - g_status[statusName]) / 10
end
else
controlmode = "4B/5B育成"
-- SS狙いがなければ普通にスコア計算
score = (characterInfo.statusTarget[statusName] - g_status[statusName]) / 10
end
-- トレーニングレベルによるスコア補正
-- トレーニング回数がLvに直結するURAシナリオのみ
if CONFIG.AUTO_MODE.SCENARIO == SCENARIO.URA then
-- 対象ステータスのトレーニングレベルが低いほど多く倍率がかかる(例:トレーニングレベル1の場合はスコア140%)
local trainingLevel = g_status[STATUS.TRAINING_LEVEL][statusName]
-- 夏合宿中はレベル5になる
if (g_status[STATUS.SEASON].index >= SEASON.CLASSIC_7A.index and g_status[STATUS.SEASON].index <= SEASON.CLASSIC_8B.index) or
(g_status[STATUS.SEASON].index >= SEASON.SENIOR_7A.index and g_status[STATUS.SEASON].index <= SEASON.SENIOR_8B.index) then
local trainingLevel = 5
end
score = score * (15 - trainingLevel) / 10
end
-- 優先度によるスコア補正
local statusPriority = characterInfo.statusPriority[statusName]
score = score * statusPriority / 100
-- ステータスボーナスによるスコア補正
-- ボーナスがあると実質的に欲しいステータスを目指す際に過剰になりやすいため、ボーナスの分だけスコアを下方補正する
score = score * (100 - g_status[STATUS.GROWTH][statusName]) / 100
-- 0から100までの範囲内に収める
if score > 100 then
score = 100
elseif score < 0 then
score = 0
end
end
return score
end