ますたーです。こんにちは。
今回は、「きのみがとれる木」を自動で揺らし、完全放置で「努力値下げきのみ」や「ぼんぐり」などを集めるArduino Leonardo自動化の記事です。
記念すべき10個目の「Arduino自動化」に関する記事です。引き続きよろしくお願いします!
なお、Arduino Leonardo自動化の導入・機材構成については導入記事を参考にしてください。
導入記事:【Arduino自動化01】Arduino開発環境の導入
※本ブログに初めてお越しの方は「本ブログについて」もぜひ、ご覧ください。
概要
本記事では、ランクマバグ状態※を利用した、きのみの自動回収を実装します。
※便宜上「ランクマバグ」と表記しますが、当ブログではランクマッチを使用しません。通信切断・初手降参の推奨もしません。
NintendoSwitch Ver.11.0アップデート対応済です。
★2021/9/20追記:NintendoSwitch Ver.13.0アップデート対応済です。
★2022/10/23追記:NintendoSwitch Ver.15.0アップデート対応済です。
では、目次です。
つくったきっかけ
きのみ・ぼんぐりの自動回収については、すでに沢山のブログで紹介・掲載されていると思います。一方で、当ブログへの検索流入を調べたところ「ぼんぐり 自動化」で検索してアクセスされる方が一定数いらっしゃるため、おそらくまだまだ需要があるかと思いましたので、更新するに至った次第です。
また、他のブログでは、先月のNintendo SwitchのVer.11のアップデート(Nintendo OnlineボタンがHome画面に実装された奴)に対応していないものも一定数見受けられるため、そういう意味でも需要があるかな、と思います。
一応、ベーシックな「きのみ高速回収のやりかた」に沿って執筆していますので、Arduinoをお持ちでない方にも楽しく読めるように心がけています。
なお、「きのみ回収の使い方も手順も知っとるわ!ソースコードだけくれ!」 という方は読み飛ばしてください⇒読み飛ばす
集めたいきのみ・ぼんぐりが出やすい木を揺らそう
きのみ・ぼんぐりを効率的に集めるにあたって、「どこの木を揺らせば良いのか?」が大変重要です。
例えば、「こうげき」の基礎ポイント(努力値)を「10」下げる効果を持つ「ネコブのみ」を集める場合、7番道路やナックル丘陵の木からランダムに入手できますが、ヨロイじまの「ワークアウトの海」の木(「並ぶ島の海」側)であれば「ネコブのみ」が確定で落ちてきます(それ以外のきのみは落ちてきません)。
すなわち、揺らして手に入るきのみの種類や量が場所によって違うため、狙ったきのみが出やすい木で揺らし続けることが重要です。
特に需要が大きいかと思いますので、各種努力値下げきのみについて、下表におすすめの木の場所を纏めました(結構頑張りました)。ご参考ください。
狙う「きのみ」が落ちてくる木の場所の一覧(アルファベット表記は「ポケモン徹底攻略」に準じる)
「きのみ」の名前 |
きのみの効果 |
おすすめの場所 |
備考 |
ぼんぐり全種 |
ガンテツボールの 材料になる |
集中の森 (ヨロイじま) |
当エリア内の どの木でもOK。 ※出やすさに偏りあり |
努力値下げきのみ全種 ※個別に集める場合は それぞれ下記推奨 |
対応する努力値を 10だけ下げる |
巨人の鏡池 (ワイルドエリア) |
DLC不要。 当エリアには1本しか 木が無いため迷わない |
ザロクのみ |
「HP」努力値を 10だけ下げる |
離れ島海域(ヨロイじま)
|
ネコブのみ |
「こうげき」努力値を 10だけ下げる |
ボールレイクの湖畔(カンムリせつげん)
|
タポルのみ |
「ぼうぎょ」努力値を 10だけ下げる |
ボールレイクの湖畔(カンムリせつげん)
|
ロメのみ |
「とくこう」努力値を 10だけ下げる |
ボールレイクの湖畔(カンムリせつげん)
|
ウブのみ |
「とくぼう」努力値を 10だけ下げる |
鍛錬平原(ヨロイじま)
|
マトマのみ |
「すばやさ」努力値を 10だけ下げる |
ボールレイクの湖畔(カンムリせつげん)
|
ランクマバグ状態で効率的にきのみを回収する
ランクマバグ状態ならきのみが即復活
きのみ・ぼんぐりの効率的な回収に関しては、ランクマッチ後やYY通信のカジュアルバトルで機内モードに変更した際に日付変更ペナルティが解除されるバグ(通称:ランクマバグ)を活用します。ランクマバグ状態であれば、きのみを回収してすぐにHome画面から日付を変更することで、再度きのみを復活させることができます。
Switch2台あればランクマッチ不要で「ランクマバグ」状態に
いわゆる「ランクマバグ状態」への移行は、ランクマッチ1戦の代わりに、下記手順でも可能です。Nintendo Online未加入など、ランクマッチができない場合に重宝します。
なお、Switchを2台用意できないなどでこの方法が使えない人は素直にランクマッチで1戦してください(その場合、Nintendo Onlineへの加入が必要です)。
- YY通信で「通信対戦」を行う(ローカル通信)
- もう一台のSwitch・剣盾を使ってその通信対戦に応じる
- 戦闘が始まったらHomeボタン長押し→「機内モード」をONに変更する
- エラーが発生するのでそれを閉じて、「にげる」選択
- フィールド画面に戻ってくる(ランクマバグ状態に移行完了)
ちなみに、しっかりとランクマバグ状態に移行できているかを確認するためには、一度Home画面に戻り、もう一度ゲーム画面に戻ると分かります。ゲーム画面に復帰した際に、一瞬だけ画面全体がチラッと暗転すればOKです。
なお、【Arduino自動化05】乱数調整レイドで色違いパッチルドン探し【冠の雪原】の記事で紹介した時とは違い、今回は一度に大量の日付変更を行わない前提なので、必ずしもポケモンセンターに移動する必要はありません(画像は使いまわしです)。
「ランクマバグ状態」で、揺らしたい木の目の前でArduinoを挿すだけの簡単仕様です。
2021/9/20追記:NintendoSwitch Ver.13.0アップデート対応済(詳細はこちら)
2022/10/23追記:NintendoSwitch Ver.15.0アップデート対応済
※Switch Liteをご利用の方は「#define SWITCH_VER (15)」を「#define SWITCH_VER (12)」に書き換えてご利用ください。
#include <SwitchControlLibrary.h>
#define HOLDTIME (95)
#define SWITCH_VER (15)
void PushRL(int delay_time_ms);
int PushKey(char* keyname, int holdtime, int delaytime);
void TiltLeftStick(int direction_deg, double power, int holdtime, int delaytime);
void setup() {
for(int i=0;i<7;i++)PushRL(300);
delay(1000);
}
void loop() {
PushKey("A", HOLDTIME, 600);
PushKey("A", HOLDTIME, 900);
PushKey("A", HOLDTIME, 3200);
PushKey("B", HOLDTIME, 600);
PushKey("B", HOLDTIME, 600);
PushKey("B", HOLDTIME, 600);
PushKey("B", HOLDTIME, 600);
PushKey("B", HOLDTIME, 600);
PushKey("B", HOLDTIME, 600);
PushKey("B", HOLDTIME, 600);
PushKey("B", HOLDTIME, 600);
PushKey("B", HOLDTIME, 600);
PushKey("B", HOLDTIME, 600);
PushKey("B", HOLDTIME, 600);
PushKey("B", HOLDTIME, 600);
PushKey("B", HOLDTIME, 600);
PushKey("Home", HOLDTIME, 1000);
PushKey("down", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("A", HOLDTIME, 1500);
PushKey("down", 1500, 105);
PushKey("right", HOLDTIME, 105);
#if (SWITCH_VER >= 15)
PushKey("down", 750, 105);
#elif (SWITCH_VER >= 13)
PushKey("down", 780, 105);
#else
for(int i=0; i<4; i++){
PushKey("down", (int)HOLDTIME/2, 105);
}
#endif
PushKey("A", HOLDTIME, 500);
PushKey("down", HOLDTIME, 105);
PushKey("down", HOLDTIME, 105);
PushKey("A", HOLDTIME, 500);
PushKey("right", HOLDTIME, 105);
PushKey("right", HOLDTIME, 105);
PushKey("up", HOLDTIME, 105);
PushKey("A", HOLDTIME, 105);
PushKey("A", HOLDTIME, 105);
PushKey("A", HOLDTIME, 105);
PushKey("A", HOLDTIME, 105);
PushKey("Home", HOLDTIME, 2000);
PushKey("A", HOLDTIME, 1000);
}
void PushRL(int delay_time_ms){
SwitchControlLibrary().PressButtonR();
SwitchControlLibrary().PressButtonL();
delay(HOLDTIME);
SwitchControlLibrary().ReleaseButtonR();
SwitchControlLibrary().ReleaseButtonL();
delay(delay_time_ms);
return;
}
int PushKey(char* keyname, int holdtime, int delaytime){
if(strlen(keyname)==1){
switch(keyname[0]){
case 'A': case 'a':
SwitchControlLibrary().PressButtonA(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonA(); delay(delaytime);
break;
case 'B': case 'b':
SwitchControlLibrary().PressButtonB(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonB(); delay(delaytime);
break;
case 'X': case 'x':
SwitchControlLibrary().PressButtonX(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonX(); delay(delaytime);
break;
case 'Y': case 'y':
SwitchControlLibrary().PressButtonY(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonY(); delay(delaytime);
break;
case 'L': case 'l':
SwitchControlLibrary().PressButtonL(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonL(); delay(delaytime);
break;
case 'R': case 'r':
SwitchControlLibrary().PressButtonR(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonR(); delay(delaytime);
break;
case 'H': case 'h':
SwitchControlLibrary().PressButtonHome(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
break;
case '+': case 'p': case 'P':
SwitchControlLibrary().PressButtonPlus(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonPlus(); delay(delaytime);
break;
case '-': case 'm': case 'M':
SwitchControlLibrary().PressButtonMinus(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonMinus(); delay(delaytime);
break;
default:
break;
}
}else if(strlen(keyname)>=2){
switch(keyname[0]){
case 'z': case 'Z':
if(keyname[1]=='R'||keyname[1]=='r'){
SwitchControlLibrary().PressButtonZR(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonZR(); delay(delaytime);
}
if(keyname[1]=='L'||keyname[1]=='l'){
SwitchControlLibrary().PressButtonZL(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonZL(); delay(delaytime);
}
break;
case 'r': case 'R':
SwitchControlLibrary().MoveHat(2); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'l': case 'L':
SwitchControlLibrary().MoveHat(6); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'u': case 'U':
SwitchControlLibrary().MoveHat(0); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'd': case 'D':
SwitchControlLibrary().MoveHat(4); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().MoveHat(8); delay(delaytime);
break;
case 'H': case 'h':
SwitchControlLibrary().PressButtonHome(); delay(holdtime);
if(holdtime>0)SwitchControlLibrary().ReleaseButtonHome(); delay(delaytime);
default:
break;
}
}else{
return -1;
}
return strlen(keyname);
}
void TiltLeftStick(int direction_deg, double power, int holdtime, int delaytime){
double rad = (double)direction_deg*PI/180.0;
int x, y;
x = (double)128*sin(rad)*power;
y = (double)-128*cos(rad)*power;
x += 128; y += 128;
if(x >= 255) x=255; if(x <= 0) x=0;
if(y >= 255) y=255; if(y <= 0) y=0;
SwitchControlLibrary().MoveLeftStick(x,y);
if(holdtime> 0){
delay(holdtime);
SwitchControlLibrary().MoveLeftStick(128,128);
}
if(delaytime>0) delay(delaytime);
return;
}
結構お手軽ですね。
あとがき
今回は、いわゆる「ランクマバグ」を利用した、全自動「きのみ」「ぼんぐり」高速回収のプログラムを紹介しました。
紹介していて言うのも変な話なのですが、個人的には「ランクマバグ」という表現があまり好きではありません。というのも、一昔前まで、ランクマッチでの初手降参や、見ず知らずの人とのYY通信から機内モード(=切断)を通して「ランクマバグ」に移行することを紹介するWebサイトや動画が散見され、各人のリテラシーが問われるようなバグの活用と周知が成されていたからです。
当時の煽りを目の当たりにしていた私からすると、ランクマバグ自体が敬遠されるべきものとしてイメージされていました(ゆえに、自動化記事2つ目「【Arduino自動化02】雪中渓谷のワットショップの目玉商品を全自動回収」についても、ランクマバグを利用しない方法で作成していました)。
今でこそ、マナーアップ啓蒙も含めた紹介動画やWeb攻略情報の掲載がされており、真摯にランクマッチ1戦で紹介されたり、各人でSwitchを2台用意した上での機内モード活用が紹介されたりしているため、一昔前ほどの心配は杞憂なのでしょうが、そういった背景心情があった上での記事執筆だとご理解いただければと思います。
つきましては、釈迦に説法かとは思いますが、読者の皆様においても、上述のような「他人に迷惑がかかる方法」でのバグ活用はお控えいただくよう、お願いします。
*
ところで、2020年11月7日 に本ブログを始めてから、明日で3ヶ月を迎えます。PV数・検索流入数も少しずつですが増えてきており、お陰様でモチベーションも保ちながら更新ができています。まだまだ駆け出しの当ブログですが、もし皆様のお役に立てるところがあれば幸いです。
もし、「いつも見てます!」とか「応援してます!」と言ったハートウォーミングな御仁がいらっしゃれば、「コメント」や「はてなスター」を残していただけますと幸いです。
どうぞ、引き続きよろしくお願いいたします。
ではではc⌒っ.ω.)っ
導入記事:【Arduino自動化01】Arduino開発環境の導入
前回記事:【Arduino自動化09】ポケモンキャンプでカレー自動調理【カレーのあかし】
次の記事:【Arduino自動化11】5番道路で全自動羽集め【DLC不要】