Su_cstrakmのヒント置き場

答えはないけどヒントならあります

LioranBoard 2を使い倒してTwitch配信をおもろくしてみる ~ガチャを実装しよう編~

~導入編~
LioranBoard 2を使い倒してTwitch配信をおもろくしてみる ~導入編~ - Su_cstrakmのヒント置き場

今回はLioranBoard 2で、Twitchのチャンネルポイントで引き換えられるガチャを実装する方法を紹介します。
簡単なものから手の込んだものまで紹介しますので参考にしてみてください。

簡単なおみくじを作る

「大吉」、「吉」、「中吉」、「小吉」、「凶」の5段階からなるおみくじを作っていきましょう。
下準備として、おみくじ用のOBSのソース(中身はgifアニメ)を5つ作っておきます。
普段は動かさないので全てオフにしておきましょう。
 
 
まずはいつものようにLioranBoard 2のDeckに新規ボタンを作成しましょう(名前は適当で)。
ボタンの上で右クリック→「Edit Triggers」から「Twitch Channel Points」トリガーを選択して、トリガーにしたいチャンネルポイントを設定しましょう。

トリガー設定方法はこちらも見てね
LioranBoard 2を使い倒してTwitch配信をおもろくしてみる ~OBSのソースの切り替え編~ - Su_cstrakmのヒント置き場
 
 
次にコマンドを作成していきます。
完成品は以下の画像ような感じになりますが、長いので途中は省略しています。
 
今回は結果が5種類しかないおみくじですので、乱数発生結果をSwitch文で分岐させる方法をとっています。
 
最初の「Random」コマンドでは、乱数を発生させてます。
「Variable Name」には結果を保存する変数名を、「Minimum Value Allowed」と「Maximum Value Allowed」には乱数の最小値と最大値をそれぞれ設定します。
「Allow Float」にチェックを入れると結果が小数点数となりますが、今回は整数値がほしいのでチェックを入れていません。
ここでは変数名を「rng」、乱数の最小値を0、最大値を4としておきましょう。
 
次の「Switch Statement」コマンドと、そこから下の「Case Statement」コマンドを用いて条件分岐作っていきます。
Switch Statementコマンドの「Value」には、条件分岐のもととなる値を設定します。
ここでは先程の「rng」を設定しておきます。
 
続くCase Statementコマンドの「Text」には具体的な条件を設定します。
(Case StatementコマンドはSwitch Statementコマンドの中に作成しておきます。)
画像では乱数が0の場合と1の場合しか載せていませんが、実際には乱数発生結果が0から4までの5通りのCase Statementコマンドを作る必要があります。
 
Case Statementコマンドの中には、OBSのソースを操作するコマンドをそれぞれ作成していきます。
ソースの切り替えと効果音発生をやっているのですが、詳細はやはりこちらの記事を参照してください。
LioranBoard 2を使い倒してTwitch配信をおもろくしてみる ~OBSのソースの切り替え編~ - Su_cstrakmのヒント置き場
 

ちょっと複雑な10連ガチャを作る

……と言いたいところですが、その前に少し「Stardew Valley」というゲームについて紹介させてください。
Stardew Valleyとは、牧場物語ライクのいわゆるスローライフ系のゲームです。
このゲーム中では特定の曜日になると行商人のカートがやって来て、ランダムな10種類のアイテムを販売するというものがあります。
今回はこの行商人のカートを再現した10連ガチャを作成していきましょう。
※ここで紹介するコマンドは、実際のゲームのプログラムをほぼそのまま再現したものとなっています。10連ガチャの実装としては少々特殊ですので、あくまで作り方の一例として捉えてください。
 
行商人のカートの特徴を簡単に説明すると、

  • 10連ガチャである
  • 各アイテムの出現率に偏りがある
  • アイテムに被りがない

となりまして、このような性質をもつガチャを作ることが今回の目標です。
 
まずは行商人のカートで売られる可能性のあるアイテムのデータを用意しますが、アイテムは何百種類とあるのでSwitch文を書くのは現実的ではありません。
LioranBoard 2ではiniファイルの操作ができますので、アイテムのデータを記述しておいたiniファイルを作成し、そこからデータを取得するようにしましょう。

 
画像では一部しか表示していませんが、実際にはこれが何百行と続いています。
セクション名([ ]で囲った部分)は「items」とし、キー(=の左側)をアイテムID、値(=の右側)を" "で囲ったアイテム名とします。
ファイル名は「cartitems.ini」としておき、LioranBoard 2のexeと同じ場所に保存しておきましょう。
(IDが飛び飛びの値なのは、実際にゲーム中でもそうなっています。また各々実装する際には好きなようにIDとアイテムを設定してください。)
 
続いていつものようにLioranBoard 2のDeckに新規ボタンを作成し、ボタンの上で右クリック→「Edit Init Variables」を選択します。

Edit Init Variablesでは、JSON形式で変数の初期化を行えます。
最初に「seenitems」という名前の配列を空の状態で作っておきたいので、

{
"seenitems":[]
}

と記述して保存しておきます。
チャンネルポイントをトリガーにしたいので、いつものように「Edit Triggers」から「Twitch Channel Points」トリガーを選択して、トリガーにしたいチャンネルポイントを設定しましょう。
 
それではコマンドの作成に入っていきましょう。
今回は長いので、先にガチャの本体部分から完成品を紹介します。
(画像で表示した部分より下にもコマンドが続いています。)

 
最初の「Array Clear」コマンドで、seenitemsの中身を消去しています。
コマンド実行後でもLioranBoard 2自体が初期化されるまでは配列の中身が保持されるため、このような処理を最初に持ってきています。
seenitems自体は抽選されたアイテム名を順次保持していくのに使用します。
 
次の「Repeat」コマンドはループ処理(有限回)を行うためのもので、「Repeat Amount」に繰り返し回数を設定します。
10回アイテムの抽選を行うので、回数を10としています。
 
Repeatコマンドの中にRandomコマンドを設定し、変数名を「id」、最小値を2、最大値を790としておきます。
整数値がほしいのでAllow Floatにはチェックを入れません。
(数値はあくまでゲーム内で使用されているものなので、各々実装する際にはアイテムIDに応じて適切な値にしてください。)
 
続いてもう一つRepeatコマンドを設定します。
どうもLioranBoard 2では無限ループが設定できないみたいなので、Repeat Amountを200(十分大きな値)に設定しています。
このRepeatコマンドの中に、さらにコマンドを設定していきます。
 
「Set Local Variable」コマンドを2つ設定します。
1つ目は「Variable Name」を「id」、「Operation」を「+=」、「Variable/Number/’String’」を1にします。(idに1を加算する)
2つ目は「Variable Name」を「id」、「Operation」を「mod」、「Variable/Number/’String’」を790にします。(idを790で割った余りにする、要は値が790以上にならないようにするための処理)
 
続いて「File: Key Exists」コマンドで、iniファイルの中に該当するキーが存在するかのチェックを行います。
「File Name」を「cartitems」、「Section」を「items」、「Key」を「/$id$/」、「Save Variable As」を「check」としておきましょう。
もし該当するキーが存在していたらcheckの中身は1になっているので、その次に「If Statement」コマンドを、 「If check == 1」となるように設定しておきます。
 
If文の中身は、条件が真である場合だけを作成しておきます。(Elseの方は空欄で)
If Statementコマンドの中に「File: Load Text」コマンドを作成し、「File Name」を「cartitems」、「Section」を「items」、「Key」を「/$id$/」、「Save Variable As」を「itemname」としておきます。
これで該当するIDのアイテム名をiniファイルから取得できました。
 
ところで、行商人のカートはアイテムのダブりがありませんので、既にアイテムが抽選されているかをチェックしないといけません。
「Array Find Valueコマンドを続いて設定し、「Array Name」を「seenitems」、「Save Array Position As」を「pos」、「Find Value」を「itemname」とします。
seenitems配列の何番目にitemnameがあるかを調べ、その位置をposに格納しています。
もし配列内に同名のアイテムが無ければ、posの値は-1となります。
 
さらにIf Statementコマンドを、「If pos == -1」となるように設定します。 (つまり、既に配列内に同名のアイテムがあるなら偽となる) そのIf Statementコマンドの中に「Array Insert」コマンドを、「Array Name」が「seenitems」、「Insert Position」が「top」、「Value To insert」が「itemname」となるように設定します。
このコマンドでseenitems配列の一番上にitemnameが追加されます。
 
アイテムを追加したらRepeat(200回ループの方)を抜けたいので、「Break」コマンドを設定します。
Breakするための条件設定ができるのですが、必ず抜け出したいので「If 1 == 1」とでもしておきましょう。
IDが無かったりアイテムが既に抽選されてたりする場合は、またSet Local Variableコマンドまで処理が戻るのでidが1ずつ加算されていく処理となります。

 

ガチャ本体の処理から先は、結果をOBS上に表示する処理となっています。
「Source Change Text (GDI+)」コマンドで、テキストソースにガチャの結果を書き出しています。
「/$seenitems[(番号)]$/」と書けば、配列の特定の番号のところの値を書き出すことができます。
そこから下はOBSソース切り替えの話なので割愛します。
 

実際にチャンネルポイントを引き換えてガチャを回してみたらこんな風になります。
うちのTwitchチャンネルで行商人のカートを体験してみようね!

https://www.twitch.tv/su_cstrakm www.twitch.tv