ますたーです。こんにちは。
3つ目の記事では、n番煎じ感は否めませんが、日付バグによるワット自動回収をArduino Leonardoで自動化していきます。DLC含め大量のワットを消費する機会が増えたので、重宝すると思います。
なお、Arduino Leonardo自動化の導入・機材構成については前々記事を参考にしてください。
導入記事:【Arduino自動化01】Arduino開発環境の導入
※本ブログに初めてお越しの方は「本ブログについて」もぜひ、ご覧ください。
概要
本記事では、日付バグの併用による巣穴の2,000Wの無限回収を実装します。
2020/12/5追記:NintendoSwitch Ver.11.0アップデート対応済です。
2021/9/20追記:NintendoSwitch Ver.13.0アップデート対応済です。
2022/10/23追記:NintendoSwitch Ver.15.0アップデート対応済です。
今回の目次です。かなりシンプルです。
作ったきっかけ
DLC第1弾「鎧の孤島」でのミツバへのワット貢ぎイベントや、前の記事でも取り上げた、DLC第2弾「冠の雪原」のワットショップの高額目玉商品など、シナリオに直結しない部分で使うワット数が増えたため、気軽に使えるワット回収スクリプトが欲しいと思ったので作りました。
また、先駆者の作成ソースコードは、プログラミング負荷軽減のため、仕様が制限されていて「1月1日に日付変更してから使うこと」「31日ある月で使うこと」「年を更新するタイプ」など、私の「気軽に使いたい※」ニーズに応えるものではなかったので作りました。
※気軽に使いたい=巣穴に「ねがいのかたまり」入れてArduino挿すだけ!
使い方
至ってシンプルで、巣穴に「ねがいのかたまり」を投げ入れ、柱を立てたらそのままAを押して「みんなで挑戦」を押す手前の状態でArduino LeonardoをSwitchに挿すだけで使えます。
なお、挿して3~5秒ほど、何度かHomeボタンが押されるような挙動は仕様です。
挿してから数秒後、5秒ほどなんの操作もしていない時間がありますが、このタイミングでHome画面(Switchでゲームを選ぶ画面)になっていればOKです。もし、なっていなければ手動で1度Homeボタンを押しておいてください。
事前準備
正しく動作するための条件は下記の通りです。
- ポケモン剣盾側の設定
- 巣穴に手動で柱を立てておく(近くに草むらなどが無い場所が良い)
- NintendoSwitch側の設定
- Switch設定「時刻と時刻」の「インターネットで時間をあわせる」をOFF
- インターネットには接続しない
書いたプログラム
処理フロー
- みんなで挑戦を押す
- Homeボタンを押して「設定」へ
- 日付を1日進める
- Homeでゲームに復帰し、募集終了
- ワットを回収し、1へ戻る(ループ)
2020/12/5追記:NintendoSwitch Ver.11.0アップデート対応済(変更点はこちら)
2021/9/20追記:NintendoSwitch Ver.13.0アップデート対応済(詳細はこちら)
2022/10/23追記:NintendoSwitch Ver.15.0アップデート対応済
※Switch Liteをご利用の方は「#define SWITCH_VER (13)」を「#define SWITCH_VER (12)」に書き換えてご利用ください。
#include <SwitchControlLibrary.h>
#define HOLDTIME (95)
#define INTERVAL (105)
#define SWITCH_VER (15)
void PushHome(int delay_time_ms);
void PushA(int delay_time_ms);
void PushB(int delay_time_ms);
void move_for(char* Direction);
void move_for(char* Direction, int delay_time_ms);
void move_for(char* Direction, int hold_time_ms, int delay_time_ms);
void setup() {
PushHome(1000);
PushHome(1000);
PushHome(1000);
PushHome(1000);
PushHome(1000);
PushHome(5000);
PushHome(1000);
delay(100);
}
void loop() {
PushA(4000);
PushHome(1000);
move_for("down");
move_for("right");
move_for("right");
move_for("right");
move_for("right");
move_for("right");
PushA(1500);
move_for("down", 1500, (int)INTERVAL/4);
move_for("right");
#if (SWITCH_VER >= 15)
move_for("down", (int)750, (int)INTERVAL);
#elif (SWITCH_VER >= 13)
move_for("down", (int)780, (int)INTERVAL/2);
#else
for(int i=0; i<4; i++){
move_for("down", (int)HOLDTIME/2, (int)INTERVAL/2);
}
#endif
PushA(500);
move_for("down");
move_for("down");
PushA(500);
move_for("right");
move_for("right");
move_for("up");
PushA(INTERVAL);
PushA(INTERVAL);
PushA(INTERVAL);
PushA(INTERVAL);
PushHome(2000);
PushA(1000);
PushB(500);
PushA(1000);
PushA(4500);
PushA(500);
PushB(2500);
PushA(1500);
}
void PushHome(int delay_time_ms){
SwitchControlLibrary().PressButtonHome();
delay(210);
SwitchControlLibrary().ReleaseButtonHome();
delay(delay_time_ms);
return;
}
void PushA(int delay_time_ms){
SwitchControlLibrary().PressButtonA();
delay(HOLDTIME);
SwitchControlLibrary().ReleaseButtonA();
delay(delay_time_ms);
return;
}
void PushB(int delay_time_ms){
SwitchControlLibrary().PressButtonB();
delay(HOLDTIME);
SwitchControlLibrary().ReleaseButtonB();
delay(delay_time_ms);
return;
}
void move_for(char* Direction){
switch(Direction[0]){
case 'r':
case 'R':
SwitchControlLibrary().MoveHat(2);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(INTERVAL);
break;
case 'l':
case 'L':
SwitchControlLibrary().MoveHat(6);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(INTERVAL);
break;
case 'u':
case 'U':
SwitchControlLibrary().MoveHat(0);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(INTERVAL);
break;
case 'd':
case 'D':
SwitchControlLibrary().MoveHat(4);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(INTERVAL);
break;
default:
break;
}
}
void move_for(char* Direction, int delay_time){
switch(Direction[0]){
case 'r':
case 'R':
SwitchControlLibrary().MoveHat(2);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(delay_time);
break;
case 'l':
case 'L':
SwitchControlLibrary().MoveHat(6);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(delay_time);
break;
case 'u':
case 'U':
SwitchControlLibrary().MoveHat(0);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(delay_time);
break;
case 'd':
case 'D':
SwitchControlLibrary().MoveHat(4);
delay(HOLDTIME);
SwitchControlLibrary().MoveHat(8);
delay(delay_time);
break;
default:
break;
}
}
void move_for(char* Direction, int hold_time_ms, int delay_time_ms){
switch(Direction[0]){
case 'r':
case 'R':
SwitchControlLibrary().MoveHat(2);
delay(hold_time_ms);
SwitchControlLibrary().MoveHat(8);
delay(delay_time_ms);
break;
case 'l':
case 'L':
SwitchControlLibrary().MoveHat(6);
delay(hold_time_ms);
SwitchControlLibrary().MoveHat(8);
delay(delay_time_ms);
break;
case 'u':
case 'U':
SwitchControlLibrary().MoveHat(0);
delay(hold_time_ms);
SwitchControlLibrary().MoveHat(8);
delay(delay_time_ms);
break;
case 'd':
case 'D':
SwitchControlLibrary().MoveHat(4);
delay(hold_time_ms);
SwitchControlLibrary().MoveHat(8);
delay(delay_time_ms);
break;
default:
break;
}
}
あとがき
今回は自動でワット回収ができるプログラムを紹介しました。
実は、このプログラムのみは、日本語版・英語版・中国語版(繁体字)で動作を確認済です。ソースコードのコメント行でゲーム中のセリフを英語で書いているのは、英語版の文字送り速度に合わせてDelay()の数値を調整したからなのです。
余談ですが、文字送り速度はゲーム中の設定から「早い 普通 遅い」と選べますが、同じ「早い」でも英語の「Fast」とは文字の送られる時間が違います(日本語や中国語のほうが短いです)。
理由は明白で、我々漢字圏の人は2バイト文字なので単純計算で英語版の文字送りの2倍速になるんですね(流石に2倍はないかもですが)。
日本語版でしかデバッグしていないArduinoでの自動化プログラムを英語版で使うと「あれ、なんで動作がズレるんだ?」となりますが、意外な落とし穴が文字送り速度に隠れているんですね(体験談)。
ちなみに、本ブログでは原則として日本語版でのみ動作確認したものしか載せません。ただ、もしかしたら、プログラム中の定数「INTERVAL」や「HOLDTIME」を増やすとうまく動くかもしれません。
余談が長くなってしまいました。
ではではc⌒っ.ω.)っ
前の記事:
【Arduino自動化02】雪中渓谷のワットショップの目玉商品を全自動回収【カンムリ雪原】
次の記事:
【Arduino自動化04】パッチルドン自動受け取り(中国語・英語対応)