大家好,好久(几天)不见,我是某昨。
自从上篇结语提了一句查卡器,我就在思考查卡这件事情到底能不能行。从内容来看,一个查卡器需要以下的基本数据:
- 卡面素材,包括图标、图片等
- 卡面属性,包括技能等
有了这二者打底,其他的其实都可有可无了(比如语音之类,可以有,但相对就没那么重要了)。上一篇某种意义上可以说是解决了第一个问题,而第二个问题完全没有碰过。因此这篇文章所要讲述的就是第一个问题的延伸和第二个问题的解决。
卡面素材
我们现在已经可以获得任意一张卡面的素材了,然而,对于卡面,我们是要下载下来还是直接使用官方的图源呢?
这里测试了一下,图片是可以正常获取的,因此偷懒的话我们只要记录每张图片的 hash 就可以了:
卡面属性
说到卡面属性,我们第一个想到的获取方式就是「アイドル一覧」,然而 enza
似乎并不想这么做(当然了,这也是有原因的)。
enza
的做法是将卡面的信息整合进卡片里返回给玩家,换句话说,就是你没法单独获取卡面的信息,而必须和你所持有的卡片信息一同绑定,那获取卡片信息的方式又是怎样的呢?我们来看源码:
这张图对应的是单个 Produce Idol 的获取方式,Support 其实大同小异,因此这里就用 Produce 卡来说明好了。这里可以看到传入了一个参数 e
,那这个 e
究竟是什么呢?
主要的内容我框出来了,这个 e
表示的是 id
而不是卡面的编号,而这我们就无能为力了。这个编号我现在看来几乎没有任何规律,甚至可能是根据玩家出货顺序排序的(当然这一点无从考证)。因此这条线索相当于是断了。
想要知道卡面属性,还有什么别的方法呢?于是,自然而然地就想到了卡池:
可以看到右上角的「詳細を見る」,这就是我们这次真正的主角了。点开之后,我们会发现:
这就是关键所在了,而最重要的是,这里接收的参数是我们上文分析过的卡片ID 而非用户所持 ID。经过静态分析,我们发现其对应的 get Path
分别为 userIdols/statusMax
和 userSupportIdols/statusMax
,于是得到了下面的代码:
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Produce Idol
map = new Map();
for ({id} of idols) {
const resp = await rua.get("userIdols/statusMax", { idolId: id })
map.set(id, resp.body);
await sleep(1000)
}
// Support Idol
smap = new Map();
for ({id} of support) {
const resp = await rua.get("userSupportIdols/statusMax", { supportIdolId: id })
smap.set(id, resp.body);
await sleep(1000)
}
这里的 rua
是 request
过程中获得的,具体的获得方法也很简单,只要在任意一个请求的过程中埋下断点,然后把 window.rua
设置为断点对应的 this
就可以了。
(后来发现了更简单的方法,window.rua = primJsp([], [], [4])
(
(我一般是搜索 _request(
,然后在上面一个 Promise
返回之前埋下断点)
经过整理,我们就获得了目前 SC 中所有的卡面信息。
总结
这次卡面数据获取的成果又是一次思维转换的案例。天无绝人之路,在我们发现自己仓库中偶像的获取并非使用 ID
的时候,不知道怎么的就萌生了“那不如去看看 ガシャ 啊”的想法,并且最终证明是正确的。很有趣,非常有趣。
当然了,这样的获取也不是一点问题都没有,游戏中对于是否为限定卡在程序上并没有做出明显的界定一切都看高山的个人喜好,但对于查卡器来说就很关键了,不过这个可能可以通过读取公告的方式实现,嘛,总之办法永远是有的(