2023/02/18

【ポケモンSV×arduino03】不思議な贈り物受け取り自動化(剣盾よりキーボード入力を流用)

 ※本記事は、ポケモンSVにて不思議な贈り物の受け取りを自動化するプログラムについて解説した記事です。ポケモンSVの操作をArduino Leonardoで自動化しております。「Arduinoって何?」って方は剣盾の00回目の記事を、Arduinoの環境構築(ライブラリ含む)は01回目の記事をご覧ください。

2024/04/06:void setup内のプログラム(コメントアウト)に誤植があったため、こっそり修正。

2023/08/15:Ver1.1を公開しました。 これまで用いていた関数を3段階(start~, input~, finish~)に分割し、メニューを開く、あいことばを入力する、メニューを閉じる動作を個別に命令できるようにしました。inputのみを複数使用することで、1回のインターネット接続で複数の贈り物を受け取れるようになります。

 

2023/03/19:Ver1.02を公開しました。DLC販売に伴うメニュー画面の「追加コンテンツ」表示に対応するための設定項目を追加しました。スケッチ内「dlc_icon_command」をご確認ください。

 

本記事では、このプログラム(スケッチ)でできることや原理を解説したうえで、スケッチを配布しています。とにかくスケッチが欲しいという方は下へと読み飛ばしてください。


 

きっかけ、動機

ポケモンSVにて、ラブラブボール2個およびキョジオーンの配布が始まりました。前回公開した最序盤ストーリー自動化と組み合わせることで、1データ1回のみ受け取ることのできる不思議な贈り物を90分ごとに回収できるようになりました。不思議な贈り物受け取りにあいことばを毎回入力するのが意外と手間なので、剣盾の頃に作った不思議な贈り物シリアルコード入力自動化を流用し、同時に自動化できるようにしました。

これで何ができるの?

ポケモンSVにて非戦闘時にメニューを開き、インターネットにつないでスケッチ上にあらかじめ入力したあいことば、シリアルコードを自動で入力することで不思議な贈り物を受け取ります。プログラムを改変することで複数のシリアルコードを順に入力したり、シリアルコード不要の贈り物を受け取ったりできます。また、Switch上の複数ユーザーを順に開いて同じ贈り物を受け取ることも可能です。

なお、前回の最序盤ストーリー自動化と組み合わせて使うことが想定されるため、最序盤ストーリー自動化で公開しているスケッチにも不思議な贈り物受け取り関数を搭載しておきます。

原理、おおまかな流れ

概要

本プログラムでは、非戦闘時(メニューを開くことのできる状態)からマイコンを挿すことで、ポケポータルの不思議な贈り物を開き、あらかじめ設定したシリアルコードを入力して贈り物を受け取ります。

プログラムを編集することで、複数の贈り物を受け取ったり、複数データで受け取ったりすることも可能です。 

画面上のキーボード操作については、剣盾の不思議な贈り物受け取りのプログラムを流用しています。

 

使用方法

スケッチ上段の設定項目

giftcode1[] = "ここにコードを入力";

 にてシリアルコード・あいことばを設定し、


スケッチ下段のvoid setup()の{}内に

mysteryGiftSV(giftcode1);

を記述して実行することで、不思議な贈り物を開いて指定したコードを入力します。また、実行後はメニューを閉じて元のフィールド画面に戻るため、続けて別のコードを記述することで複数の贈り物を受け取りできます。

また、 

mysteryGiftSV();

のように、括弧内に何も指定しない場合は、シリアルコードが不要な「インターネットで受け取る」にて贈り物を受け取ります(2月末まで空を飛ぶピカチュウ)。

その他、

giveBallToFirstPokemon()...バッグの中のボール1番下(受け取ったラブラブボール)を手持ち1番上に持たせる

 changeUsers()...開いているデータにてレポートを書き、その後にHOME画面に移動、開いていたデータを閉じて1つ右隣のユーザーのデータを開き、ゲームを開始する

といった関数も用意していますので、プログラムを書き換えることで道具輸送の際の持たせる手間を減らしたり、複数データを受け取らせたりできます。


準備、必要なもの

本スケッチでは、マイコンを挿す前に以下の準備が必要となります。

0. あらかじめニンテンドーアカウントを登録しておき、ネット接続して不思議な贈り物を受け取れる状態にする
 
1. 本スケッチ内の上段(★)にあるchar giftcode1にて、入力させたいあいことば・シリアルコードを設定
 
2. スケッチ下段のvoid setup(あるいはloop)内に、おこなう動作を命令する
    mysteryGiftSV(giftcode1); でgiftcode1に設定したコードを入力、
    ()内を空白にすればコード無しの「インターネットで受け取る」を選択
    複数の贈り物の受け取り、ユーザーを切り替えながら連続して受け取りなど、状況に応じて編集
 
3. ポケモンSVにて非戦闘時(メニューを開ける状態)、コライドンミライドンに乗っていない状態でマイコンを挿してスタート。

2023/03/19追記:DLC販売によるメニュー画面右下の「追加コンテンツ」表示による十字キー入力回数の変化に対応するため、dlc_icon_commandという設定項目を追加しました。設定項目中の

const int dlc_icon_command=1;の値を、「追加コンテンツ」表示がなければ0を、表示されていれば1に設定してください。

作成したスケッチ

作成した不思議な贈り物受け取り自動化のスケッチ2024.04.06_Ver1.101はこちら

旧スケッチ2023.03.19_Ver1.02はこちら。2023.02.18_Ver1.01はこちら

2023/08/15:Ver1.1を公開しました。 これまで用いていた関数を3段階(start~, input~, finish~)に分割し、メニューを開く、あいことばを入力する、メニューを閉じる動作を個別に命令できるようにしました。inputのみを複数使用することで、1回のインターネット接続で複数の贈り物を受け取れるようになります。

 

2023/03/19:Ver1.02を公開しました。DLC販売に伴うメニュー画面の「追加コンテンツ」表示に対応するための設定項目を追加しました。スケッチ内「dlc_icon_command」をご確認ください。 

最序盤ストーリー自動化Ver2.0以降のスケッチにも一部の関数を搭載しています。ストーリーを自動化し、そのまま贈り物を受け取りたい場合はmysteryGiftSV(giftcode1)を実行するように編集してください。

本スケッチを実際に使用した動画はこちら(Ver1.0)

 

最序盤ストーリー自動化Ver2.1解説動画の最後に、受け取り自動化Ver1.1の追加要素の解説(start~,input~,finish~)もしています。動画の20:15以降から不思議な贈り物の解説です。

スケッチ(Ver1.0)


/**
* ふしぎなおくりもの受け取り自動化@ポケモンSV
* ふしぎなおくりものを開き、指定したシリアルコードを入力して受け取る
* 何もシリアルコードを指定しない場合、「インターネットで受け取る」を選択する(空を飛ぶピカチュウなど)
*
* 初期条件は以下の通り
* 0. あらかじめニンテンドーアカウントを登録しておき、ネット接続して不思議な贈り物を受け取れる状態にする
* 1. 本スケッチ内の上段(★)にあるchar giftcode1にて、入力させたいあいことば・シリアルコードを設定
* 2. スケッチ下段のvoid setup(あるいはloop)内に、おこなう動作を命令する
*  mysteryGiftSV(giftcode1); でgiftcode1に設定したコードを入力、
*  ()内を空白にすればコード無しの「インターネットで受け取る」を選択
*  複数の贈り物の受け取り、ユーザーを切り替えながら連続して受け取りなど、状況に応じて編集
* 3. ポケモンSVにて非戦闘時(メニューを開ける状態)、コライドンミライドンに乗っていない状態でマイコンを挿してスタート。
*
*/

// ★以下に'ふしぎなおくりものシリアルコード'を入力。大文字or数字のみ(Oオー,Iアイ,Zジィーなどは数字012に置き換え注意)
// 入力ミスは考慮していないため、要確認。大文字か、OIZを使っていないか。
char giftcode1[] = "L0VEL0VEL0VE";
// ★複数ユーザーのストーリーを進め、それぞれ別のコードを入力する場合は各データごとにシリアルコードを設定
char giftcode2[] = "1STCHAMPSV";
// キーボード配列。
char key[4][11] = {"1234567890",
                   "QWERTYU??P",
                   "ASDFGHJKL?",
                   "?XCVBNM???"};
#include <auto_command_util.h>
// Switchスリープ用関数
void sleepNow()
{
  SwitchController().pressButton(Button::HOME);
  delay(1500);
  SwitchController().releaseButton(Button::HOME);
  pushButton(Button::A, 1000);
}
// バッグ内ボールの1番下を、手持ちの1番上のポケモンに持たせる
// ラブラブボールを通信交換で送る用に作成
void giveBallToFirstPokemon(){
    // メニューを開き、左側の手持ち1番上を選択
    pushButton(Button::X, 1000);
    pushHatButton(Hat::LEFT, 300);
    pushHatButtonContinuous(Hat::UP, 1500);
    pushButton(Button::A, 500);
    // 上から4番目、持ち物を持たせる
    pushHatButton(Hat::DOWN, 200, 3);
    pushButton(Button::A, 2000);
    // バッグ内、ボールの1番下を選択
    pushHatButton(Hat::RIGHT, 200);
    pushHatButton(Hat::UP, 200);
    pushButton(Button::A, 500, 4);
    pushButton(Button::B, 200, 10);
    delay(300);
}
// バッグ内ボールの1番下を、手持ちの2番目のポケモンに持たせる
// ラブラブボールを通信交換で送る用に作成
void giveBallToSecondPokemon(){
    // メニューを開き、左側の手持ち2番目を選択
    pushButton(Button::X, 1000);
    pushHatButton(Hat::LEFT, 300);
    pushHatButtonContinuous(Hat::UP, 1500);
    pushHatButton(Hat::DOWN, 300);
    pushButton(Button::A, 500);
    // 上から4番目、持ち物を持たせる
    pushHatButton(Hat::DOWN, 200, 3);
    pushButton(Button::A, 2000);
    // バッグ内、ボールの1番下を選択
    pushHatButton(Hat::RIGHT, 200);
    pushHatButton(Hat::UP, 200);
    pushButton(Button::A, 500, 4);
    pushButton(Button::B, 200, 10);
    delay(300);
}
// メニュー下から3番目のポケポータル→1番下のふしぎなおくりものを選択、シリアルコード/合言葉を入力して受け取り。
// あらかじめ上記でgiftCodeを設定すること。
// 引数に何も入力しなかった場合、「インターネットで受け取る」を選択する
void mysteryGiftSV(char gift[] = "@"){
    // フィールド上でメニューを開く
    pushButton(Button::X, 1000);
    // カーソルが左(手持ちポケモン)にある場合は右に移る
    pushHatButton(Hat::RIGHT, 300);
    // カーソルを1番下まで長押し
    pushHatButtonContinuous(Hat::DOWN, 1500);
    // 上に2回、ポケポータルを選択、6秒待機
    pushHatButton(Hat::UP, 300, 2);
    pushButton(Button::A, 6000);
    // 上1回、カーソルを1番下に移動、不思議な贈り物選択、2.5秒待機
    pushHatButton(Hat::UP, 300);
    pushButton(Button::A, 2500);
    // ここから、シリアルコードの有無で分岐、受け取ってポケポータルの画面に戻るまで
    // 引数にシリアルコードを指定していない場合、1番上の「インターネットで受け取る」を選択
    // giftCodeを指定した場合、2番目の「シリアルコード/あいことばで受け取る」を選択
    if(gift == "@"){
      // 「インターネットで受け取る」を選択、そのままA連打25秒で配布物を選択する
      pushButton(Button::A, 100, 125);
      // Bボタン連打35秒、「インターネットで受け取る」等の選択肢まで戻る
      pushButton(Button::B, 100, 130);
      delay(500);
      // 最後に押したBのタイミングで、インターネットを切断するか聞かれる選択肢が表示されるかされないかの2通りの状況になる
      // 下入力2回、はい/いいえを聞かれている場合は「はい」にカーソル、聞かれていない場合は不思議な贈り物を確認するにカーソル
      pushHatButton(Hat::DOWN, 300, 2);
      // ABBA入力、前者なら「はい」を選択してネット切断、後者なら1度贈り物を確認してから戻り「はい」を選択して切断
      pushButton(Button::A, 700);
      pushButton(Button::B, 700, 2);
      pushButton(Button::A, 700);
    }else{
      // 2番目の「シリアルコード/あいことばで受け取る」を選択、インターネット接続、多めにA連打してシリアルコード入力画面で11111
      pushHatButton(Hat::DOWN, 300);
      pushButton(Button::A, 100, 80);
      // B長押しで無駄に入力した11111を消す
      SwitchController().pressButton(Button::B);
      delay(2500);
      SwitchController().releaseButton(Button::B);
      // キーボード入力開始
      keyTyping(gift);
      // A連打、B連打で受け取りを完了し、「インターネットで受け取る」等の選択肢まで戻る
      pushButton(Button::A, 100, 80);
      pushButton(Button::B, 100, 150);
      // 最後に押したBのタイミングで、インターネットを切断するか聞かれる選択肢が表示されるかされないかの2通りの状況になる
      // 下入力1回、はい/いいえを聞かれている場合は「いいえ」にカーソル、聞かれていない場合は不思議な贈り物を確認するにカーソル
      pushHatButton(Hat::DOWN, 300);
      // A下A入力、前者なら「いいえ」を選択してから贈り物を確認、後者ならすぐに贈り物を確認してそのまま
      pushButton(Button::A, 700);
      pushHatButton(Hat::DOWN, 300);
      pushButton(Button::A, 700);
      // BBA入力、贈り物確認を終えてインターネット切断「はい」
      pushButton(Button::B, 700, 2);
      pushButton(Button::A, 700);
    }
    // 不思議な贈り物を終えたら、B連打でフィールドに戻る
    pushButton(Button::B, 100, 50);
    delay(500);
}
// キーボードが開かれたところで指定されたコードを1文字ずつ入力し、最後に決定する
void keyTyping(char code[]){
    // 初期位置を指定。左上角を0,0とする
    int nowPosition[2] = {0, 0};
    // 1文字ずつ、文字が何行目、何列目かを確認
    for (int n = 0; n < strlen(code); n++){
      int gyo = 0;
      int retsu = 0;
      for (int i = 0; i < 4; i++){
        for (int j = 0; j < 10; j++){
          if (code[n] == key[i][j]){
            gyo = i;
            retsu = j;
            break;
          }
        }
        if (code[n] == key[gyo][retsu]){
          break;
        }
      }
      // 何文字↓、→に動かすかを確認(負の場合は逆方向)
      int sita = gyo - nowPosition[0];
      int migi = retsu - nowPosition[1];
      if (sita < 0){
        pushHatButton(Hat::UP, 100, sita * -1);
      } else {
        pushHatButton(Hat::DOWN, 100, sita);
      }
      if (migi < 0){
        pushHatButton(Hat::LEFT, 100, migi * -1);
      } else {
        pushHatButton(Hat::RIGHT, 100, migi);
      }
      pushButton(Button::A, 100);
      // 入力後の位置を現在位置として設定
      nowPosition[0] = gyo;
      nowPosition[1] = retsu;
    }
    // +ボタンで入力完了
    pushButton(Button::PLUS, 100, 2);
}
// フィールド上で、メニューを開いてレポートを書き、その後ホーム画面へ、
// 進行したユーザーから、1つ右隣のユーザーへと切り替える
void changeUsers(){
    pushButton(Button::B, 100, 5);
    delay(500);
    // Xボタンメニュー
    pushButton(Button::X, 1000);
    // Rボタンセーブ
    pushButton(Button::R, 1000);
    pushButton(Button::A, 4000);
    // セーブ完了、メニューを閉じる
    pushButton(Button::B, 800, 2);
    // HOMEボタンからユーザー切り替え
    pushButton(Button::HOME, 1000);
    pushButton(Button::Y, 800);
    pushButton(Button::A, 5000);
    // 1つ右隣のユーザーを選択、動けるところまで待機
    // 「本体更新」が出る場合は更新せずに始める
    pushHatButton(Hat::UP, 300);
    pushHatButton(Hat::RIGHT, 300);
    pushButton(Button::A, 500);
    pushHatButton(Hat::RIGHT, 300);
    pushButton(Button::A, 15000);
    pushButton(Button::A, 1000, 30);
}
// B連打する場面があるため、コライドンミライドンから下りることを推奨
void setup(){
    // 最初の数回の入力はswitchが認識しない場合があるので、無駄打ちをしておく
    pushButton(Button::A, 300, 13);
    delay(500);
    // あらかじめ指定したシリアルコードを入力して受け取り
    mysteryGiftSV(giftcode1);
    // 複数個の贈り物を続けて受け取ることも可能
    mysteryGiftSV(giftcode2);
    /* 必要な命令文を組み合わせて、複数贈り物を受け取り、ユーザーを切り替えて受け取りなど可能
    // (括弧内)に何も指定していない場合はシリアルコードなしの贈り物を受け取り
    mysteryGiftSV();
    // ラブラブボールを輸送する場合、手持ち1番目のポケモンに持たせる
    giveBallToFirstPokemon();
    // 手持ち2匹目にももたせる(ポケモン1匹のみの場合は不可)
    giveBallToSecondPokemon();
    // セーブしてソフトを終了し、1つ右隣のユーザーを選択してポケモンSVを開きなおす
    changeUsers();
    // Switch本体をスリープさせる
    sleepNow();
    */
}
void loop(){
    delay(30000);
}

 

 

最後に

本スケッチを使用することで、ポケモンSVの不思議な贈り物を自動で受け取ることができます。1データで受け取るだけであれば人力で済ませた方が楽なのですが、いくつも受け取ろうとするとキーボード入力などが意外と手間になります。

前回の最序盤ストーリー自動化と組み合わせて使ったり、Switch内の8ユーザーで順番に受け取ったりする場合にご利用ください。

 

プログラムの不備、改善点などありましたらコメントやお問い合わせからお願いいたします。

Arduino Arduino Leonardo (ピンソケット・ピンヘッダ実装済) 【A000057】
by カエレバ

0 件のコメント:

コメントを投稿

【ポケモンSV×pokecon01】テラレイドローカルゲスト周回自動化【arduino04と連携】

 ※本記事は、ポケモンSVにて固定した テラレイドのローカル通信のゲスト側のレイド周回によるアイテム・ポケモン入手 を自動化するプログラムについて解説した記事です。 今回は Poke-Controller を利用しつつ、前回公開した ホスト側 の自動化プログラム( SV×Ardu...