Yarimono

Yarimono

Not enough ratings
【一次性交易大师】本地HTML图鉴工具
By la_la_la
本工具可读取本地图鉴与存档数据,生成可视化界面,且无需下载软件,记事本粘贴代码后浏览器打开即可
本工具不提供修改存档的功能,仅仅是方便工具(做全精灵成就好用),想修改存档的可自行研究
   
Award
Favorite
Favorited
Unfavorite
一、功能介绍
  1. 查看图鉴:本工具可查看所有精灵的种族值、个性、技能列表,并提供搜索功能,方便捉到精灵后辨别是否值得培养;
  2. 查看存档:本工具可读取任意存档,标记未开图鉴的精灵与仓库中的精灵,显示精灵在仓库中的位置(开图鉴好用,可以方便的看到前置精灵是什么,仓库里是否有,在仓库的什么位置。原生仓库没有查找功能,眼花了都找不到精灵)
二、制作方法
  1. steam库中右键游戏->管理->浏览本地文件,打开游戏所在目录;
  2. 新建文本文档(txt),将下方附录中的代码复制粘贴进来,保存;
  3. 回到文件夹,修改文档后缀,将txt改为html(没看到后缀的在文件夹上方 查看->显示文件扩展名),文件名自己随便起,建议index.html
  4. 制作完成

参考资料:
修改rpgsave文件[blog.csdn.net]
rpgmvp格式图片转png[www.bilibili.com]
三、使用方法
使用方法有两种:
  1. 直接浏览器打开
  2. 本地http服务器打开(推荐)
由于跨域的原因,直接浏览器打开无法读取本地文件,需要手动选择本地文件,并且无法读取精灵图片,因此推荐开启本地http服务器
下面分别介绍使用方法:
1. 直接浏览器打开
  1. 双击打开文件即可,打开后没有数据,需要自行选择文件上传数据;
  2. 先打开图鉴数据文件(位于游戏所在目录下的data\www\data_cn,选择N_Yarimon_DB.json)
  3. 再打开存档数据文件(位于游戏所在目录下的data\www\save,选择file1.rpgsave,file后面的数字是存档号,要查看哪个存档就选择哪个)
  4. 图鉴数据文件打开一次即可,存档数据文件可以重复打开,游戏里保存存档后需要重新打开
2. 本地http服务器打开
  1. 以游戏所在目录为根目录开启http服务器(开启http服务器的工具有很多,python可以开、vscode有插件可以开、Everything也可以开,大家自行百度选择适合自己的即可)
  2. 打开浏览器,输入http://localhost:8000(端口号是自己设的),点开你制作的html(如果是index.html的话应该不用点开就是了)
  3. 右边选择存档就能用了
附录
字数卡的太极限了🙏
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, initial-scale=1.0"><title>性交易图鉴</title><script src="https://code.jquery.com/jquery-3.6.0.min.js"></script><script async src="https://cdn.jsdelivr.net/npm/lz-string@1.4.4/libs/lz-string.min.js"></script><style>body{font-family:Arial,sans-serif;display:flex;flex-direction:row;height:100vh;margin:0}#sidebar{width:20%;border-right:1px solid#ccc;overflow-y:auto;max-height:100vh;padding-top:60px;box-sizing:border-box}#searchContainer{position:fixed;top:0;width:18%;background-color:#fff;z-index:1;padding:10px;box-shadow:0px 4px 4px rgba(0,0,0,0.1)}#searchBox{width:96%;padding:8px;font-size:1em}#pokemonList{list-style:none;padding:0;margin:0}.pokemonItem{padding:10px;cursor:pointer}.unget{background-color:#fae0e0}.inbox{background-color:#fafae0}.select{background-color:#e0fafa}#pokemonDetails{width:60%;padding:20px;overflow-y:auto;max-height:100vh;box-sizing:border-box}img{max-width:150px;display:block;margin-bottom:10px}.skillItem{margin:10px 0;padding:8px;border:1px solid#ccc;border-radius:5px;background-color:#f9f9f9}.skillDetails{margin-top:5px;font-size:0.9em;color:#555}#rightSide{width:20%;overflow-y:auto;max-height:100vh;padding-top:60px;box-sizing:border-box}#filemode{left:10%;position:relative;display:inline-block;font-family:Arial,sans-serif}input[type="file"]{position:absolute;opacity:0;width:100%;height:100%;top:0;left:0;cursor:pointer}.file-btn{display:inline-block;padding:10px 20px;background-color:#a0a0a0;color:white;border:none;border-radius:5px;font-size:16px;font-weight:bold;cursor:pointer;transition:background-color 0.3s}.file-name{margin-top:20px;color:#555;vertical-align:middle;max-width:200px}#httpmode{left:10%;position:relative;font-family:Arial,sans-serif}.file-choice{list-style-type:none;padding-left:0px;width:80%}.file-choice li{padding:10px;background:#fff;border:1px solid#ddd;margin-bottom:10px;border-radius:5px;cursor:pointer}.file-choice li:hover{background-color:#f0f0f0}.explain{margin-top:10px;color:#555;font-size:15px;position:relative;left:10%;width:80%}</style></head><body><div id="sidebar"><div id="searchContainer"><input type="text"id="searchBox"placeholder="搜索ID或精灵名"></div><ul id="pokemonList"></ul></div><div id="pokemonDetails"class="hidden"><h2>Yarimon信息</h2><img id="pokemonImage"src="data\www\icon\icon.png"alt="精灵图片"><p><strong>身高:</strong><span id="height"></span>m</p><p><strong>重量:</strong><span id="weight"></span>kg</p><p><strong>进化等级:</strong><span id="evolv"></span></p><p><strong>属性:</strong><span id="type"></span></p><h3>种族值:<span id="racevalue"></span></h3><p><strong>血量:</strong><span id="hp"></span></p><p><strong>攻击:</strong><span id="attack"></span></p><p><strong>防御:</strong><span id="defense"></span></p><p><strong>速度:</strong><span id="speed"></span></p><p><strong>个性:</strong><span id="individual"></span></p><p id="individual_des"></p><div id="monboxList"></div><h3>技能列表</h3><div id="skillList"></div></div><div id="rightSide"><div id="filemode"><button class="file-btn">选择文件</button><input type="file"id="fileInput"><div class="file-name"><p>先打开图鉴数据文件<br>(data\www\data_cn\N_Yarimon_DB.json)</p><p>再打开存档数据文件<br>(data\www\save\file1.rpgsave,file后面的数字是存档号)</p></div></div><div id="httpmode"><h3>选择存档:</h3><ul class="file-choice"id="fileList">正在加载文件...</ul></div><div class="explain">左侧目录红色代表未开图鉴精灵,黄色代表在仓库精灵</div></div><script>const pngHeader=new Uint8Array([0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,0x00,0x00,0x00,0x0D,0x49,0x48,0x44,0x52]);let mZukanDatas=[],wazaDatas=[],tokuseiDatas=[];const unfetch=location.protocol==='file:';const decryptRpgmvp=async file=>{const uint8Array=new Uint8Array(await file.arrayBuffer());const decryptedArray=new Uint8Array(uint8Array.length);decryptedArray.set(pngHeader,0);decryptedArray.set(uint8Array.slice(32),16);return new Blob([decryptedArray],{type:"image/png"})};const displayDecryptedImage=async filePath=>{const decryptedBlob=await decryptRpgmvp(await(await fetch(filePath)).blob());$('#pokemonImage').attr('src',URL.createObjectURL(decryptedBlob))};const parseRpgSave=async file=>{try{const decompressed=LZString.decompressFromBase64(await file.text());return JSON.parse(decompressed)}catch{return null}};const updatePokemonData=saveData=>{mZukanDatas.forEach(p=>p.unget=p.boxlist=null);saveData.system.yZukan['@a'].forEach(z=>{if(!z.getFlg){const p=mZukanDatas.find(p=>p.id===z.id);if(p)p.unget=true}});saveData.system.MonBox['@a'].forEach((page,i)=>{page['@a'].forEach((m,j)=>{if(m){const p=mZukanDatas.find(p=>p.id===m.id);if(p)(p.boxlist||(p.boxlist=[])).push({page:i+1,pos:j+1,lv:m.lv})}})})};const displayPokemonList=list=>{const $list=$('#pokemonList').empty();list.forEach(p=>{const name=p.name_Locs.find(n=>n.locName==='cn')?.value||'';if(name){$list.append($('<li>').addClass('pokemonItem').toggleClass('unget',!!p.unget).toggleClass('inbox',!!p.boxlist).text(`${p.id}-${name}`).on('mouseenter',function(){$('.pokemonItem').removeClass('select');$(this).addClass('select');showDetails(p)}))}})};function filterPokemonList(searchTerm){const filteredPokemon=mZukanDatas.filter(p=>p.id.toString().includes(searchTerm)||(p.name_Locs.find(n=>n.locName==='cn')?.value||'').includes(searchTerm));displayPokemonList(filteredPokemon)}const showDetails=p=>{if(!unfetch)displayDecryptedImage(`data/www/img/pictures/H_Scene/_DataBase/Zukan/Monster/${p.picPath}.rpgmvp`);$('#height').text(p.ecology.takasa);$('#weight').text(p.ecology.omosa);$('#evolv').text(p.sinka_lv);const{hp,atk,def,agi,type}=p.state;$('#type').text(type);$('#hp').text(hp);$('#attack').text(atk);$('#defense').text(def);$('#speed').text(agi);$('#racevalue').text(hp+atk+def+agi);const t=tokuseiDatas.find(t=>t.id===p.tokuseiId);$('#individual').text(t.name_Locs.find(loc=>loc.locName==='cn').value);$('#individual_des').text(t.setu_Locs.find(loc=>loc.locName==='cn').value);$('#monboxList').html(`<strong>备战空间:</strong>`+p.boxlist?.map(b=>`<p>第${b.page}页第${b.pos}位-Lv:${b.lv}</p>`).join('')).toggle(!!p.boxlist);$('#skillList').html(p.wazaList.map(w=>{const s=wazaDatas.find(s=>s.id===w.id);return`<div class="skillItem"><strong>${s.name_Locs.find(loc=>loc.locName==='cn').value}</strong>(学习等级:${w.lv})<div>属性:${s.type}|威力:${s.iryoku}|命中:${s.hit}|冷却:${s.kaisu}|先制:${s.yusendo}</div><div class="skillDetails">${s.setu_Locs.find(loc=>loc.locName==='cn').value}</div></div>`}).join(''))};const loadFileByIndex=async i=>{try{const response=await fetch(`data/www/save/file${i}.rpgsave?${Math.random()}`);return response.ok?await response.blob():null}catch{return null}};const loadFiles=async()=>{const validFiles=[];for(let i=1;i<=20;i++){const file=await loadFileByIndex(i);if(file)validFiles.push({index:i,content:file})}displayFileList(validFiles)};const displayFileList=files=>{const $fileList=$('#fileList').empty();if(files.length===0){$fileList.append('<li>没有存档文件</li>');return}files.forEach(({index})=>{$fileList.append($('<li>').text(`存档${index}`).on('click',async()=>{const file=await loadFileByIndex(index);if(file){const saveData=await parseRpgSave(new File([file],`file${index}.rpgsave`));updatePokemonData(saveData);displayPokemonList(mZukanDatas)}}))})};const initPokemonData=data=>{({mZukanDatas,wazaDatas,tokuseiDatas}=data);displayPokemonList(mZukanDatas);$('#searchBox').on('input',()=>filterPokemonList($('#searchBox').val().trim().toLowerCase()))};$(()=>{if(unfetch){$('#filemode').show();$('#httpmode').hide();$('#fileInput').on('change',async e=>{const file=e.target.files[0];if(!file)return;if(file.name.endsWith('.json')){initPokemonData(JSON.parse(await file.text()))}else if(file.name.endsWith('.rpgsave')){updatePokemonData(await parseRpgSave(file));displayPokemonList(mZukanDatas)}})}else{$('#filemode').hide();$('#httpmode').show();$.getJSON('data/www/data_cn/N_Yarimon_DB.json').then(data=>{initPokemonData(data);loadFiles()}).catch(err=>console.error('加载数据失败:',err))}});</script></body></html>
5 Comments
睡觉去睡觉去丶 1 Jul @ 11:17pm 
图鉴打开了怎么修改存档啊?
ASDCFF 13 Feb @ 5:06am 
图片不显示怎么办
la_la_la  [author] 4 Jan @ 1:33am 
修改等级可以做到,用制作方法->参考资料第一个网址的代码修改存档就行。图鉴就不加这个功能了,懒得写
咲花 13 Dec, 2024 @ 6:49am 
大佬有没有能直接修改主角等级的方法
Tesla Zhang 13 Dec, 2024 @ 5:51am 
牛逼