LoLでデスしたらエルシャダイ流すやつを作った【そんなコードで大丈夫か】

# 作ったもの
（音が出ます）
<iframe width="560" height="315" src="https://www.youtube.com/embed/lRhEm8YRlO4?si=yQRo8klkIapBD8dG" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

# 作ったきっかけ
AdventCalendarのネタを考えていたところ、長年プレイしているLeague of Legendsのlive client dataが取得できるということを知り、これで何かやるしかないぜ！となりました。
でも省エネでやりたい...ので初めてChatGPTの力を借りて作ることにしました（無課金GPT3.5）。
省エネというからにはドキュメントなんかほぼ読まずにGPTママに全部丸投げするんだい

# 何をどうやって作ろう
どうせならゲームのイベントと連動して動くようなものを作りたいけど、デスクトップアプリの造詣が皆無。どうやって作ればいいかわからないよぉ。

ということでChatGPTに聞いてみたらpythonでできるよと教えてくれたのでpythonで作ることにしました。

# データの取得
ゲーム中にここに公開されているURLをたたくと試合のデータがjsonで返ってきます。
スキルの使用等取得できないものもあります。（[サンプルデータはこちら](https://static.developer.riotgames.com/docs/lol/liveclientdata_sample.json)）

https://developer.riotgames.com/docs/lol#game-client-api_live-client-data-api



どうやらこれを一定間隔で取得して差分を取るしかイベントの変化を検知できないようです。
面倒臭い...と思ってgithubを眺めていたら、なんと有志がそれ用のライブラリを公開してくれていました！助かる

https://github.com/agroth01/LeagueOfEvents

早速readmeのexampleを動かしてみると、普通にイベントを取得できました。

# エルシャダイを流す
うーんうーん、何か面白いことはできないだろうか...とミジンコほどのギャグセンスをフル回転させてやっと思いついたのが、

**「デスしたらエルシャダイの映像を流す」**

でした。終わっとるでほんま。

でもやることが決まったらあとはChatGPTちゃんにコードを書いてもらうだけ。そう思っていた時期が僕にもありました。

少しずつ進めていきました。

やりたいことは
- LoLのデスイベントを取得（これはライブラリで完結）
- 映像を流す

だけですが、全然わからないのでChatGPTに丸投げで映像を流すコードを生成してもらい、ウィンドウが半透明フルスクリーンになるように修正してもらい、たまに嘘をつかれてキレそうになり...しばらく格闘していると、それらしいものが出来上がりました。

使用しているライブラリはもちろんのこと、pythonも全然触ったことないですがそれらしいものができてしまうことに感動しながらその日の作業を終了し、床に就きました。

# 動かなくなる
次の日、続きをやろうと思い、とりあえず昨晩の動いていたコードを実行してみたところ、なんと動かなくなっていました。

まさに何もしていないのに壊れたというやつです。


...いや待てよ、さっき**LoLのアップデート**したな。

いやしかし使用しているライブラリの最終アップデートは１年以上前。それが昨日動いたのに今日動かないことってあるか？と思いながらレスポンスを確認すると、少しだけ変わっていました。（ユーザ名が`AKADA`から`AKADA#JP1`になっていました）

forkして該当の箇所を修正して解決（少しの変更で良かった...）

# 完成
あとはちょっとコードを手直しして、再生用の動画作って完成～

一応リスポーンしたらそんな装備で大丈夫か？って言ってくれるやつもあります
<iframe width="560" height="315" src="https://www.youtube.com/embed/iLqmva8Xvlo?si=_Bn8Gup2eT-qFiEd" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

[素材元](https://elshaddai.jp/elshaddai_crim/freedeta.html)（エルシャダイの素材って公開されているんですね、うれしい）

[Steam版エルシャダイ](https://store.steampowered.com/app/1581040/El_Shaddai_ASCENSION_OF_THE_METATRON_HD_Remaster/)もあるみたいです。
ネタに使っておいて未プレイなので買います。


<br/>
<details><summary>デスしたらエルシャダイが流れるコード</summary><div>

```python
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QDesktopWidget
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtCore import Qt, QUrl
import leagueofevents

class VideoPlayer(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()
        self.initVideo()

    def initUI(self):
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowStaysOnTopHint)
        self.setWindowTitle("Video Player")
        screen_resolution = QDesktopWidget().screenGeometry()
        self.setGeometry(screen_resolution)
        self.setWindowOpacity(0.7)

        self.video_widget = QVideoWidget(self)
        self.video_widget.setGeometry(screen_resolution)


        layout = QVBoxLayout()
        layout.addWidget(self.video_widget)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        self.media_player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.media_player.setVideoOutput(self.video_widget)
        self.media_player.setVolume(20)
        self.media_player.stateChanged.connect(self.on_media_state_changed)

    def initVideo(self):
        file_path = '動画のパス'

        self.media_player.setMedia(QMediaContent(QUrl.fromLocalFile(file_path)))
        self.media_player.play()

    def on_media_state_changed(self, state):
        if state == QMediaPlayer.StoppedState:
            self.media_player.stop()
            self.close()

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            self.media_player.stop()
            self.close()

def onDeath():
    app = QApplication(sys.argv)
    player = VideoPlayer()
    player.show()
    app.exec_()

if __name__ == '__main__':
    leagueofevents.subscribe_to_event("onDeath", onDeath)

```

</div></details>

# 感想
省エネが目標だったのに思ったより手間がかかって疲れました。
来年はもっと省エネできるように装備を充実させたいです。