0
0
mirror of https://github.com/marcrobledo/savegame-editors.git synced 2025-04-24 16:35:10 +00:00

merged botw and botw master editors into one, also fixed loading savegames from mods and other QoL additions

This commit is contained in:
Marc Robledo 2020-02-16 23:34:04 +01:00
parent f4e2fc05ad
commit de1aa9fc49
16 changed files with 45819 additions and 1374 deletions

View File

@ -48,6 +48,13 @@ h1{text-align:center;color:#49c5ff;margin:3% 0;}
.game{background-color:#353535}
.game:hover{background-color:#434343}
.game>div{padding: 15px 10px}
.game b{
background-color:yellow;
color:black;
font-size:80%;
padding: 2px 4px;
border-radius:3px;
}
hr{
border:none;
border-top:1px solid #333;
@ -96,19 +103,20 @@ h6 a:hover{
<a class="three columns game" href="smash-bros-ultimate/"><img src="thumb.png" id="thumb-smash-bros-ultimate" /><div>Super Smash Bros. Ultimate <b>NEW!</b></div></a>
</div>
<div class="row">
<a class="four columns game" href="team-kirby-clash-dx/"><img src="thumb.png" id="thumb-team-kirby-clash-dx" /><div>Team Kirby Clash Deluxe</div></a>
<a class="four columns game" href="pokemon-shuffle/"><img src="thumb.png" id="thumb-pokemon-shuffle" /><div>Pokémon Shuffle</div></a>
<a class="four columns game" href="sushi-striker/"><img src="thumb.png" id="thumb-sushi-striker" /><div>Sushi Striker <b>NEW!</b></div></a>
<a class="four columns game" href="final-fantasy-explorers/"><img src="thumb.png" id="thumb-final-fantasy-explorers" /><div>Final Fantasy Explorers</div></a>
<a class="four columns game" href="kirbys-blowout-blast/"><img src="thumb.png" id="thumb-kirbys-blowout-blast" /><div>Kirby's Blowout Blast</div></a>
<a class="four columns game" href="pokemon-picross/"><img src="thumb.png" id="thumb-pokemon-picross" /><div>Pokémon Picross</div></a>
</div>
<div class="row">
<a class="four columns game" href="pokemon-picross/"><img src="thumb.png" id="thumb-pokemon-picross" /><div>Pokémon Picross</div></a>
<a class="four columns game" href="rhythm-paradise-megamix/"><img src="thumb.png" id="thumb-rhythm-paradise-megamix" /><div>Rhythm Paradise Megamix</div></a>
<a class="four columns game" href="kirbys-blowout-blast/"><img src="thumb.png" id="thumb-kirbys-blowout-blast" /><div>Kirby's Blowout Blast</div></a>
<a class="four columns game" href="team-kirby-clash-dx/"><img src="thumb.png" id="thumb-team-kirby-clash-dx" /><div>Team Kirby Clash Deluxe</div></a>
<a class="four columns game" href="streetpass-mii-plaza/"><img src="thumb.png" id="thumb-streetpass-mii-plaza" /><div>StreetPass Mii Plaza</div></a>
<a class="four columns game" href="mario-kart-7/"><img src="thumb.png" id="thumb-mario-kart-7" /><div>Mario Kart 7</div></a>
</div>
<div class="row">
<a class="four columns game" href="picross-3d-round-2/"><img src="thumb.png" id="thumb-picross-3d-round-2" /><div>Picross 3D: Round 2</div></a>
<a class="four columns game" href="rhythm-paradise-megamix/"><img src="thumb.png" id="thumb-rhythm-paradise-megamix" /><div>Rhythm Paradise Megamix</div></a>
</div>
<hr/>

View File

@ -1,83 +0,0 @@
/*
Cache Service Worker template by mrc 2019
mostly based in:
https://github.com/GoogleChrome/samples/blob/gh-pages/service-worker/basic/service-worker.js
https://github.com/chriscoyier/Simple-Offline-Site/blob/master/js/service-worker.js
https://gist.github.com/kosamari/7c5d1e8449b2fbc97d372675f16b566e
Note for GitHub Pages:
there can be an unexpected behaviour (cache not updating) when site is accessed from
https://user.github.io/repo/ (without index.html) in some browsers (Firefox)
use absolute paths if hosted in GitHub Pages in order to avoid it
also invoke sw with an absolute path:
navigator.serviceWorker.register('/repo/_cache_service_worker.js', {scope: '/repo/'})
*/
/* MOD: fix old caches for mrc */
caches.keys().then(function(cacheNames){
for(var i=0; i<cacheNames.length; i++){
if(
cacheNames[i]==='runtime' ||
/^precache-\w+$/.test(cacheNames[i]) ||
/^precache-editor-([\w\+]+)-\w+$/.test(cacheNames[i]) ||
/^v?\d+\w?$/.test(cacheNames[i])
){
console.log('deleting old cache: '+cacheNames[i]);
caches.delete(cacheNames[i]);
}
}
});
var PRECACHE_ID='zelda-botw-master-editor';
var PRECACHE_VERSION='v2b';
var PRECACHE_URLS=[
'/savegame-editors/zelda-botw-master/','/savegame-editors/zelda-botw-master/index.html',
'/savegame-editors/zelda-botw-master/zelda-botw-master.css',
'/savegame-editors/zelda-botw-master/zelda-botw-master.js',
'/savegame-editors/zelda-botw-master/hashes.js',
'/savegame-editors/zelda-botw-master/favicon.png',
'/savegame-editors/savegame-editor.js'
];
// install event (fired when sw is first installed): opens a new cache
self.addEventListener('install', evt => {
evt.waitUntil(
caches.open('precache-'+PRECACHE_ID+'-'+PRECACHE_VERSION)
.then(cache => cache.addAll(PRECACHE_URLS))
.then(self.skipWaiting())
);
});
// activate event (fired when sw is has been successfully installed): cleans up old outdated caches
self.addEventListener('activate', evt => {
evt.waitUntil(
caches.keys().then(cacheNames => {
return cacheNames.filter(cacheName => (cacheName.startsWith('precache-'+PRECACHE_ID+'-') && !cacheName.endsWith('-'+PRECACHE_VERSION)));
}).then(cachesToDelete => {
return Promise.all(cachesToDelete.map(cacheToDelete => {
console.log('delete '+cacheToDelete);
return caches.delete(cacheToDelete);
}));
}).then(() => self.clients.claim())
);
});
// fetch event (fired when requesting a resource): returns cached resource when possible
self.addEventListener('fetch', evt => {
if(evt.request.url.startsWith(self.location.origin)){ //skip cross-origin requests
evt.respondWith(
caches.match(evt.request).then(cachedResource => {
if (cachedResource) {
return cachedResource;
}else{
return fetch(evt.request);
}
})
);
}
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1,68 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Savegame Editor &ndash; The legend of Zelda: Breath of the wild (Master editor)</title>
<meta http-equiv="content-Type" content="text/html; charset=UTF-8"/>
<meta name="description" content="A savegame editor for The legend of Zelda: Breath of the wild. This master version allows you to edit everything in the savegame."/>
<meta name="keywords" content="html5, savegame, save, editor, hack, exploit, wii u, zelda, breath of the wild, botw, weapon, durability, modifier, horse, epona, korok, unlocker, dlc, amiibo"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
<link rel="shortcut icon" href="./favicon.png"/>
<link type="text/css" rel="stylesheet" href="./zelda-botw-master.css" media="all"/>
<script type="text/javascript" src="../savegame-editor.js"></script>
<script type="text/javascript" src="./zelda-botw-master.js"></script>
<script type="text/javascript" src="./hashes.js"></script>
<script type="text/javascript"><!--
/* service worker */
var FORCE_HTTPS=true;
window.addEventListener('load',function(){
if(location.protocol==='http:' && FORCE_HTTPS)
location.replace(window.location.href.replace('http:','https:'));
else if(location.protocol==='https:' && 'serviceWorker' in navigator)
navigator.serviceWorker.register('/savegame-editors/zelda-botw-master/_cache_service_worker.js', {scope: '/savegame-editors/zelda-botw-master/'});
}, false);
--></script>
</head>
<body>
<!-- HEADER -->
<div id="header">
<div id="header-top">
<div class="row wrapper padding-vertical">
<h1>Savegame Editor for The legend of Zelda: BOTW (Master Editor)</h1>
<div class="six columns text-left">Zelda: BOTW Savegame Master Editor</div>
<div class="six columns text-right header-buttons">
by <a href="/" class="author">Marc Robledo</a>
<a href="https://github.com/marcrobledo/savegame-editors/tree/master/zelda-botw-master" target="_blank" class="button"><span class="sprite github"></span> See on GitHub</a>
<a href="https://www.paypal.me/marcrobledo/5" target="_blank" rel="nofollow" class="donate button"><span class="sprite heart"></span> Donate</a>
</div>
</div>
</div>
<div id="toolbar" class="hidden padding-vertical">
<div class="row wrapper">
<div class="twelve columns text-center">
<span class="clickable" onclick="SavegameEditor.changeEndianess()" id="span-version"></span> |
<label for="select-filters">Filter: </label>
<select id="select-filters" onchange="SavegameEditor.showHashes(parseInt(this.value), 0)">
<option value="-1">- All -</option>
</select>
<label for="select-page">Page: </label>
<button id="page-prev" onclick="if(document.getElementById('select-page').selectedIndex>0)SavegameEditor.showHashes(parseInt(document.getElementById('select-filters').value), parseInt(document.getElementById('select-page').value)-1)">&laquo;</button>
<select id="select-page" onchange="SavegameEditor.showHashes(parseInt(document.getElementById('select-filters').value), parseInt(this.value))"></select>
<button id="page-next" onclick="if(document.getElementById('select-page').selectedIndex<document.getElementById('select-page').children.length-1)SavegameEditor.showHashes(parseInt(document.getElementById('select-filters').value), parseInt(document.getElementById('select-page').value)+1)">&raquo;</button> |
<button class="button with-icon icon3" onclick="closeFile()">Close file</button>
<button class="button colored blue with-icon icon9" onclick="saveChanges()">Save changes</button>
</div>
</div>
</div>
</div>
<!-- THE EDITOR -->
<div id="the-editor" class="wrapper hidden">
<table id="table"></table>
</div>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

View File

@ -1,559 +0,0 @@
/* Zelda BOTW Savegame editor by Marc Robledo v20170521 */
/* minify at https://cssminifier.com/ + https://www.base64-image.de/ (sprites */
/* @FONT-FACES */
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700,800');
body{
font:15px 'Open Sans',sans-serif;
cursor:default;
margin:180px 0 80px;
background-color:#160c0c;
color:#f9f5da;
}
table{
border-collapse:collapse;
}
tr{border-bottom:1px solid #452e2e}
tr:hover{background-color:#250e0e}
/* flex box */
.row{
display:flex;
flex-flow:row wrap; /* this is the same as flex-direction:row;flex-wrap:wrap; */
align-items:center; /* vertical align */
justify-content:space-between
}
.columns.c1,.columns.one{width:7.33333%}
.columns.c2,.columns.two{width:15.66667%}
.columns.c3,.columns.three{width:24%}
.columns.c4,.columns.four{width:32.33333%}
.columns.c5,.columns.five{width:40.66667%}
.columns.c6,.columns.six{width:49%}
.columns.c7,.columns.seven{width:57.33333%}
.columns.c8,.columns.eight{width:65.66667%}
.columns.c9,.columns.nine{width:74%}
.columns.c10,.columns.ten{width:82.33333%}
.columns.c11,.columns.eleven{width:90.66667%}
.columns.c12,.columns.twelve{width:99%}
/* grid box */
.row-items{
background-color:rgba(0,0,0,.4);
position:relative;
margin-bottom:4px;
padding:10px;
}
.row-items img{max-width:100%}
.row-items img:hover{background-color:#222}
.item-number{position:absolute;top:0;left:0; color:#444;font-family:monospace;font-size:80%}
.tiles span{display:block}
/* useful classes */
.help:hover{cursor:help}
.hidden{display:none}
.mono{}
.clickable{cursor:pointer} /* also Safari iOS fix for clickable elements */
.text-ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.text-left{text-align:left}
.text-right{text-align:right}
.text-center{text-align:center}
.text-justify{text-align:justify}
.padding-vertical{padding:20px 0}
.round{border-radius:3px}
/* colors */
.bg-light-gray{background-color:rgba(216,216,216,.99)}
.bg-mid-gray{background-color:rgba(144,144,144,.99);color:white}
.bg-dark-gray{background-color:rgba(72,72,72,.99);color:white}
.bg-red{background-color:#e74c3c}
.bg-orange{background-color:#f39c12}
.bg-blue{background-color:#3498db}
.bg-green{background-color:#25ba84}
.fnt-white{color:white}
.fnt-light-gray{color:#d8d8d8}
.fnt-mid-gray{color:#909090}
.fnt-dark-gray{color:#48484}
.fnt-red{color:#e74c3c}
/*.fnt-red{color:#fe5d05}*/
.fnt-orange{color:#f39c12}
/*.fnt-orange{color:#feb806}*/
.fnt-blue{color:#3498db}
.fnt-green{color:#25ba84}
/*.fnt-green{color:#9ac430}*/
.border-white{border-color:white}
.border-light-gray{border-color:#d8d8d8}
.border-mid-gray{border-color:#909090}
.border-dark-gray{border-color:#48484}
.border-red{border-color:#e74c3c}
.border-orange{border-color:#f39c12}
.border-blue{border-color:#3498db}
.border-green{border-color:#25ba84}
/* Icons */
span.sprite,span.icon,button.with-icon:before{
background-image: url('data:image/png;base64,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');
background-position:0px 0px;
display:inline-block;
vertical-align:middle
}
span.sprite{width:24px;height:24px}
span.icon,button.with-icon:before{
width:16px;height:16px;
margin-right:4px;
content:""
}
button.with-icon.icon0:before{background-position:-0px -16px}
button.with-icon.icon1:before{background-position:-16px -16px}
button.with-icon.icon2:before{background-position:-32px -16px}
button.with-icon.icon3:before{background-position:-48px -16px}
button.with-icon.icon4:before{background-position:-64px -16px}
button.with-icon.icon5:before{background-position:-80px -16px}
button.with-icon.icon6:before{background-position:-96px -16px}
button.with-icon.icon7:before{background-position:-112px -16px}
button.with-icon.icon8:before{background-position:-128px -16px}
button.with-icon.icon9:before{background-position:-144px -16px}
button.with-icon.icon10:before{background-position:-160px -16px}
button.with-icon.colored.icon0:before{background-position:-0px -32px}
button.with-icon.colored.icon1:before{background-position:-16px -32px}
button.with-icon.colored.icon2:before{background-position:-32px -32px}
button.with-icon.colored.icon3:before{background-position:-48px -32px}
button.with-icon.colored.icon4:before{background-position:-64px -32px}
button.with-icon.colored.icon5:before{background-position:-80px -32px}
button.with-icon.colored.icon6:before{background-position:-96px -32px}
button.with-icon.colored.icon7:before{background-position:-112px -32px}
button.with-icon.colored.icon8:before{background-position:-128px -32px}
button.with-icon.colored.icon9:before{background-position:-144px -32px}
button.with-icon.colored.icon10:before{background-position:-160px -32px}
span.icon.icon0,button.with-icon.transparent.icon0:before{background-position:-0px 0px}
span.icon.icon1,button.with-icon.transparent.icon1:before{background-position:-16px 0px}
span.icon.icon2,button.with-icon.transparent.icon2:before{background-position:-32px 0px}
span.icon.icon3,button.with-icon.transparent.icon3:before{background-position:-48px 0px}
span.icon.icon4,button.with-icon.transparent.icon4:before{background-position:-64px 0px}
span.icon.icon5,button.with-icon.transparent.icon5:before{background-position:-80px 0px}
span.icon.icon6,button.with-icon.transparent.icon6:before{background-position:-96px 0px}
span.icon.icon7,button.with-icon.transparent.icon7:before{background-position:-112px 0px}
span.icon.icon8,button.with-icon.transparent.icon8:before{background-position:-128px 0px}
span.icon.icon9,button.with-icon.transparent.icon9:before{background-position:-144px 0px}
span.icon.icon10,button.with-icon.transparent.icon10:before{background-position:-160px 0px}
span.sprite{width:24px;height:24px}
span.sprite.github{background-position:0px -48px;width:16px;height:16px; margin-right:5px}
span.sprite.heart{background-position:-16px -48px;width:16px;height:16px; margin-right:5px}
button.with-icon.file-load:before{background-position:-32px -48px;width:20px;height:20px; margin-right:8px}
/* header+toolbar+footer */
#header{
color:#333;
position:absolute;
top:0;left:0;
width:100%;
z-index:100;
background-color:#faf8f7;
}
#header:after{
display:block;
position:absolute;
bottom:-3px;
left:0;
width:100%;
height:3px;
background-image:linear-gradient(to right, #0f0404 0%, #b99f65 40%, #b99f65 40%, #b99f65 65%, #0f0404 100%);
content:"";
}
#toolbar{
padding:8px
}
#span-version:hover{text-decoration:underline}
#toolbar select{width:initial !important}
#page-prev,#page-next{min-width:initial !important}
#header h1{display:none}
#header h1 img{vertical-align:middle}
.header-buttons{
font-size:85%
}
.header-buttons a.author{
color:#333;
text-decoration:none;
border-bottom:1px solid #d3cec3;
margin-right:10px
}
.header-buttons a.author:hover{
border-color:#83d8ff
}
.header-buttons a.button{
text-decoration:none;
color:white;
background-color:#1a415d;
padding:10px 20px;
border-radius:3px
}
.header-buttons a.button:hover{
background-color:#153044
}
.donate.button{
background-color:#51a451 !important;
/*text-shadow:0 -1px 0 #37a137 !important;
background:radial-gradient(#60bd60,#398a39);*/
animation:donateglow 2s infinite
}
.donate.button:hover{background-color:#3e903e !important}
@keyframes donateglow{
0%{box-shadow:none}
50%{box-shadow:#d8ff7c 0 0 8px inset}
100%{box-shadow:none}
}
hr{border:none;border-top:1px dotted #bbb;margin:15px 0}
h3{
border-bottom:2px solid #888;
font-size:135%;
padding:10px 0;
text-transform:uppercase;
color:#b99f65
}
table{width:100%}
th{background-color:#d4d4d4}
/* forms */
input[type=text],input[type=number],select{
padding:6px 8px;
width:250px;
max-width:90%;
font:100% 'Open Sans', sans-serif;
border:1px solid #888;
border-radius:2px;
box-sizing:border-box
}
input[type=text]:hover,input[type=number]:hover,select:hover{
border-color:#666
}
input[type=text]:focus,input[type=number]:focus,select:focus{
box-shadow:#63bce5 0 0 4px 1px;
border-color:#47a8df
}
input[type=text].error,input[type=number].error,select.error{
box-shadow:#f88 0 0 4px 1px;
border-color:red
}
input[type=text].small,input[type=number].small,select.small{width:70px}
input[type=text].medium,input[type=number].medium,select.medium{width:130px}
.full-width{width:100% !important;max-width:100% !important}
#the-editor input[type=text],#the-editor input[type=number],#the-editor select{
border:1px solid #444;
border-radius:2px;
background-color:#111;
color:white;
}
#the-editor input[type=text]:hover,#the-editor input[type=number]:hover,#the-editor select:hover{
border-color:#666
}
#the-editor input[type=text]:focus,#the-editor input[type=number]:focus,#the-editor select:focus{
box-shadow:rgba(185,159,101,.5) 0 0 4px 1px;
background-color:#222;
border-color:#b99f65
}
/* buttons */
button{
font-family:inherit;
font-size:100%;
min-width:120px;
border-radius:2px;border:1px solid;border-color:#ccc #ccc #b3b3b3;
padding:6px 12px;
margin:0 5px;
background-color:#f0f0f0;
background-image:linear-gradient(to bottom, #fff, #e6e6e6);
text-shadow:0 1px 0 #f8f8f8;
color:#333;
box-shadow:0px 1px 0px rgba(255, 255, 255, 0.2) inset;
transition:border-color ease-in-out .15s;
box-sizing:border-box
}
button.small{
min-width:1px
}
button:hover{
text-shadow:none;
border-color:#999999
}
button:active{
background-image:none;
transform:translate(0px,1px);
border-color:#888;
text-shadow:none;
box-shadow:0 2px 8px -3px rgba(0, 0, 0, 0.5) inset;
background-color:#eeeeee;
transform:translateY(1px)
}
button:focus{}
button:disabled{opacity:.35}
button.colored{color:white !important}
button.colored.blue{
box-shadow:0 1px 0 rgba(120, 200, 230, 0.5) inset;
background-color:#21759B;
background-image:linear-gradient(to bottom, #2A95C5, #21759B);
border-color:#21759B #21759B #1E6A8D;
text-shadow:0 -1px 0 #20749a
}
button.colored.blue:hover{
box-shadow:0 1px 0 rgba(120, 200, 230, 0.6) inset;
background-color:#278AB7;
background-image:linear-gradient(to bottom, #2E9FD2, #21759B);
border-color:#1B607F;
text-shadow:0 -1px 0 #1b6080
}
button.colored.blue:active{
box-shadow:0 2px 8px -3px rgba(0, 0, 0, 0.5) inset;
background:linear-gradient(to bottom, #21759B, #278AB7) repeat scroll 0 0 #1B607F;
border-color:#124560 #0e74a3 #0e74a3;
text-shadow:0 -1px 0 #177ea4
}
button.colored.red{
box-shadow:0 1px 0 #df4c45 inset;
background-color:#b72319;
background-image:linear-gradient(to bottom, #ce271d, #a41f17);
border-color:#a41f17 #a41f17 #951d15;
text-shadow:0 -1px 0 #a01d15
}
button.colored.red:hover{
box-shadow:0 1px 0 #e8564f inset !important;
background-color:#bf261c !important;
background-image:linear-gradient(to bottom, #db2c20, #a52017) !important;
border-color:#871a13 !important;
text-shadow:0 -1px 0 #8b1b14 !important
}
button.colored.red:active{
box-shadow:0 2px 8px -3px rgba(0, 0, 0, 0.5) inset !important;
background:linear-gradient(to bottom, #a51f17, #c1251b) repeat scroll 0 0 #b22118 !important;
border-color:#66140c #a0150d #a0150d !important;
text-shadow:0 -1px 0 #a41e17 !important
}
button.colored.green{
box-shadow:0 1px 0 #81cf81 inset !important;
background-color:#59b259 !important;
background-image:linear-gradient(to bottom, #61c261, #51a351) !important;
border-color:#52a452 #4f9f4f #448944 !important;
text-shadow:0 -1px 0 #37a137 !important
}
button.colored.green:hover{
box-shadow:0 1px 0 #99de99 inset !important;
background-color:#278AB7 !important;
background-image:linear-gradient(to bottom, #64ce64, #51a351) !important;
border-color:#3f7f3f !important;
text-shadow:0 -1px 0 #1c9216 !important
}
button.colored.green:active{
box-shadow:0 2px 8px -3px rgba(0, 0, 0, 0.5) inset !important;
background:linear-gradient(to bottom, #1e8f22, #23a627) repeat scroll 0 0 #219b24 !important;
border-color:#105815 #17941b #17941b !important;
text-shadow:0 -1px 0 #17a417 !important
}
button.colored.orange{
box-shadow:0 1px 0 #ffb519 inset !important;
background-color:#e69501 !important;
background-image:linear-gradient(to bottom, #fda502, #d08400) !important;
border-color:#d38500 #c97e00 #b46f00 !important;
text-shadow:0 -1px 0 #8f5901 !important
}
button.colored.orange:hover{
box-shadow:0 1px 0 #ffc03c inset !important;
background-color:#e69501 !important;
background-image:linear-gradient(to bottom, #ffb01e, #d08400) !important;
border-color:#a36300 !important;
text-shadow:0 -1px 0 #95620f !important
}
button.colored.orange:active{
box-shadow:0 2px 8px -3px rgba(0, 0, 0, 0.5) inset !important;
background:linear-gradient(to bottom, #c07400, #ed9500) repeat scroll 0 0 #219b24 !important;
border-color:#53400b #886912 #886912 !important;
text-shadow:0 -1px 0 #654e0e !important
}
button.transparent{
min-width:auto;
box-shadow:none;
padding:0;
background:none;
text-decoration:underline;
border:none;
text-shadow:none;
color:black !important
}
button.transparent:hover{background-color:rgba(0,0,0,.05)}
button.no-text.with-icon:before{margin-right:0px}
.wrapper{
max-width:920px;
margin:0 auto
}
/* MarcDragAndDrop */
#dragzone{
border:4px dashed #b99f65;
color:#b99f65;
text-align:center;
border-radius:8px;
position:relative;
transition:all .2s;
padding-bottom:20px;
/*font-weight:bold;*/
}
.dragging-files #dragzone{
border-color:#3498db;
color:#3498db;
background-color:white
}
#dragzone-message{
font-size:180%;
margin:128px 0;
line-height:2
}
#demo{
text-decoration:none;
padding:4px 16px;
border-radius:3px;
clear:both;
position:relative;
top:80px;
}
#demo:hover{
background-color:#bbb;
color:#000
}
#warning{
position:fixed;
bottom:-80px;
width:100%;
background-color:#a30202;
background-color:rgba(164,0,0,.96);
color:white;
transition:bottom .5s
}
#warning.visible{bottom:0px}
#warning:hover{background-color:#b31212}
#warning u{
background-color:white;
color:#b31212;
text-decoration:none;
padding:6px 16px;
border-radius:3px;
font-weight:bold
}
/* responsive */
@media only screen and (max-width:961px){
.wrapper{max-width:auto; padding-left:10px;padding-right:10px;}
}
@media only screen and (max-width:721px){
#header .columns-6,#header .columns.six{width:100%;text-align:center}
#the-editor{font-size:13px}
}
@media only screen and (max-width:481px){
#the-editor{font-size:12px}
}
/* MarcDialogs */
#dialog-about{background-color:#ffd823}
.dialog-overlay,.dialog{visibility:hidden;opacity:0}
.dialog-overlay.active,.dialog.active{visibility:visible;opacity:1;transition-delay:0s}/* fixes fade-in/fade-out*/
.dialog-overlay{
transition:visibility 0s .2s, opacity .2s;
background-color:black;
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=75)";/* IE8 */
background-color:rgba(255,255,255,.65)
}
.dialog{
position:absolute;top:0;left:0; /* fix for reserved space */
transform:translateY(-10px);
transition:visibility 0s .2s, opacity .2s ease-in, transform .2s ease-in;
background-color:white;
padding:15px;
min-width:360px;
max-width:80%;
border-radius:4px;
box-shadow:rgba(0,0,0,.5) 0 0 10px;
line-height:1.8;
color:#333;
}
.dialog.active{transform:translateY(0px)}
.buttons{
margin-top:20px;
text-align:center
}

View File

@ -1,367 +0,0 @@
/*
The legend of Zelda: Breath of the wild - Master editor v20190625
by Marc Robledo 2017-2019
*/
var currentEditingItem=0;
SavegameEditor={
Name:'The legend of Zelda: Breath of the wild (Master editor)',
Filename:'game_data.sav',
Version:20190625,
/* Constants */
Constants:{
STRING_SIZE:0x20,
STRING64_SIZE:0x80,
//missing versions: 1.1.1, 1.1.2 and 1.4.1
VERSION: ['v1.0', 'v1.1', 'v1.2', 'v1.3', 'v1.3.1', 'Kiosk', 'v1.3.3','v1.3.4', 'v1.4', 'v1.5', 'v1.6', 'v1.6*', 'v1.6**','v1.6***'],
FILESIZE: [896976, 897160, 897112, 907824, 907824, 916576, 1020648, 1020648, 1027208, 1027208, 1027216, 1027216, 1027216, 1027216],
HEADER: [0x24e2, 0x24ee, 0x2588, 0x29c0, 0x2a46, 0x2f8e, 0x3ef8, 0x3ef9, 0x471a, 0x471b, 0x471e, 0x0f423d, 0x0f423e,0x0f423f]
},
HashFilters:[
['Amiibo', /WolfLink_|Amiibo/],
['Display flag names', /_DispNameFlag$/],
['DLC1', /100enemy/],
['DLC2', /Motorcycle/],
['Horses', /Horse_/],
['Defeated enemies', /Defeat_Enemy_|Defeated.+Num/],
['Items', /Porch|Cook/],
['Get flags', /IsGet_/],
['Korok', /HiddenKorok|OldKorok_/],
['Visited locations', /^Location_/],
['Compendium', /AlbumPicture|PictureBook/]
],
Hashes:[],
/* private functions */
_toHexInt:function(i){var s=i.toString(16);while(s.length<8)s='0'+s;return '0x'+s},
_writeBoolean:function(offset,val,arrayPos){if(arrayPos)tempFile.writeU32(offset+8*arrayPos,val?1:0);else tempFile.writeU32(offset,val?1:0)},
_writeValue:function(offset,val,arrayPos){if(arrayPos)tempFile.writeU32(offset+8*arrayPos,val);else tempFile.writeU32(offset,val)},
_writeFloat32:function(offset,val,arrayPos){if(arrayPos)tempFile.writeF32(offset+8*arrayPos,val);else tempFile.writeF32(offset,val)},
_writeString:function(offset,str){
for(var i=0; i<8; i++){
tempFile.writeBytes(offset,[0,0,0,0]);
var fourBytes=str.substr(i*4, 4);
for(j=0; j<fourBytes.length; j++){
tempFile.writeU8(offset+j, fourBytes.charCodeAt(j));
}
offset+=8;
}
},
_writeString64:function(offset,str){
for(var i=0; i<16; i++){
tempFile.writeBytes(offset,[0,0,0,0]);
var fourBytes=str.substr(i*4, 4);
for(j=0; j<fourBytes.length; j++){
tempFile.writeU8(offset+j, fourBytes.charCodeAt(j));
}
offset+=8;
}
},
_readString:function(offset){
var txt='';
for(var j=0; j<8; j++){
txt+=tempFile.readString(offset,4);
offset+=8;
}
return txt
},
_readString64:function(offset){
var txt='';
for(var j=0; j<16; j++){
txt+=tempFile.readString(offset,4);
offset+=8;
}
return txt
},
changeEndianess:function(){
var tempFileByteSwapped=new MarcFile(tempFile.fileSize);
tempFileByteSwapped.fileType=tempFile.fileType;
tempFileByteSwapped.fileName=tempFile.fileName;
tempFileByteSwapped.littleEndian=!tempFile.littleEndian;
for(var i=0; i<tempFile.fileSize; i+=4){
tempFileByteSwapped.writeU32(i, tempFile.readU32(i));
}
tempFile=tempFileByteSwapped;
this.checkValidSavegame();
},
/* check if savegame is valid */
_checkValidSavegameByConsole:function(switchMode){
var CONSOLE=switchMode?'Switch':'Wii U';
tempFile.littleEndian=switchMode;
for(var i=0; i<this.Constants.FILESIZE.length; i++){
var versionHash=tempFile.readU32(0);
if(versionHash===0x2a46) //v1.3.0 switch?
versionHash=0x29c0;
else if(versionHash===0x3ef9) //v1.3.3 switch?
versionHash=0x3ef8;
else if(versionHash===0x471b) //v1.5 is the same as 1.4
versionHash=0x471a;
if(tempFile.fileSize===this.Constants.FILESIZE[i] && versionHash===this.Constants.HEADER[i] && tempFile.readU32(4)===0xffffffff){
setValue('version', this.Constants.VERSION[i]+' ('+CONSOLE+')');
return true;
}
}
return false
},
checkValidSavegame:function(){
return this._checkValidSavegameByConsole(false) || this._checkValidSavegameByConsole(true);
},
preload:function(){
for(var i=0; i<this.HashFilters.length; i++){
var option=document.createElement('option');
option.value=i;
option.innerHTML=this.HashFilters[i][0];
document.getElementById('select-filters').appendChild(option);
}
},
showHashes:function(regexFilter, page){
var findHashesIn;
empty('table');
this.Hashes=[];
if(regexFilter===-1){
findHashesIn=HASHES;
}else if(regexFilter>-1){
findHashesIn={};
for(var hash in HASHES){
if(this.HashFilters[regexFilter][1].test(HASHES[hash][1])){
findHashesIn[hash]=true;
}
}
}
var previousHashValue=0;
for(var i=0x0c; i<tempFile.fileSize-4; i+=8){
var hashValue=tempFile.readU32(i);
if(hashValue===previousHashValue)
continue;
previousHashValue=hashValue;
if(findHashesIn[hashValue]){
this.Hashes.push({
type:HASHES[hashValue][0],
id:HASHES[hashValue][1],
offset:i
});
}else if(regexFilter===-1){
this.Hashes.push({
id:'* '+this._toHexInt(hashValue)
});
}
}
this.Hashes.sort(function(a,b){
if(a.id<b.id)return -1;
if(a.id>b.id)return 1;
return 0;
});
var HASHES_PER_PAGE=100;
var nPages=parseInt(this.Hashes.length/HASHES_PER_PAGE);
if(this.Hashes.length%HASHES_PER_PAGE!==0){
nPages++;
}
empty('select-page');
for(var i=0; i<nPages; i++){
var option=document.createElement('option');
option.value=i;
option.innerHTML=i+1;
document.getElementById('select-page').appendChild(option);
}
document.getElementById('select-page').selectedIndex=page;
this.Hashes=this.Hashes.splice(page*HASHES_PER_PAGE, HASHES_PER_PAGE);
var placeholder=document.createElement('tbody');
for(var i=0; i<this.Hashes.length; i++){
var hash=this.Hashes[i];
if(hash.type){
createHashInput(placeholder, hash.id, hash.type, hash.offset)
}else{
addEditorRow(placeholder, hash.id);
}
}
get('table').appendChild(placeholder);
},
/* load function */
load:function(){
tempFile.fileName='game_data.sav';
this.showHashes(-1, 0);
document.getElementById('select-filters').value=-1;
},
/* save function */
save:function(){}
}
function addEditorRow(container, left, right){
var tr=document.createElement('tr');
tr.appendChild(document.createElement('td'));
tr.appendChild(document.createElement('td'));
tr.children[1].className='text-right';
if(right){
tr.children[0].appendChild(label(right.id, left));
tr.children[1].appendChild(right);
}else{
tr.children[0].innerHTML=left;
}
container.appendChild(tr);
}
function createHashInput(container, hashId, type, offset){
if(type===BOOL){
var c=checkbox(hashId);
c.offset=offset+4;
c.addEventListener('change', setBoolean);
if(tempFile.readU32(offset+4))
c.checked=true;
addEditorRow(container, hashId, c);
}else if(type===S32){
var inp=inputNumber(hashId, 0, 0xffffffff, tempFile.readU32(offset+4));
inp.offset=offset+4;
inp.addEventListener('change', setS32);
addEditorRow(container, hashId, inp);
}else if(type===F32){
var inp=inputNumber(hashId, 0, 0xffffffff, tempFile.readF32(offset+4));
inp.offset=offset+4;
inp.addEventListener('change', setF32);
addEditorRow(container, hashId, inp);
}else if(type===VECTOR2F){
createHashInput(container, hashId+'[0]', F32, offset);
createHashInput(container, hashId+'[1]', F32, offset+8);
}else if(type===VECTOR3F){
createHashInput(container, hashId+'[0]', F32, offset);
createHashInput(container, hashId+'[1]', F32, offset+8);
createHashInput(container, hashId+'[2]', F32, offset+16);
}else if(type===VECTOR4F){
createHashInput(container, hashId+'[0]', F32, offset);
createHashInput(container, hashId+'[1]', F32, offset+8);
createHashInput(container, hashId+'[2]', F32, offset+16);
createHashInput(container, hashId+'[3]', F32, offset+24);
}else if(type===STRING){
var inp=input(hashId, SavegameEditor._readString(offset+4));
inp.offset=offset+4;
inp.maxLength=32;
inp.addEventListener('change', setString);
addEditorRow(container, hashId, inp);
}else if(type===STRING64){
var inp=input(hashId, SavegameEditor._readString64(offset+4));
inp.offset=offset+4;
inp.maxLength=64;
inp.addEventListener('change', setString64);
addEditorRow(container, hashId, inp);
}else if(type===BOOL_ARRAY){
var hash=tempFile.readU32(offset);
var nextHash=hash;
var i=0;
while(nextHash===hash){
createHashInput(container, hashId+'['+i+']', BOOL, offset+i*8);
i++;
nextHash=tempFile.readU32(offset+i*8);
}
}else if(type===S32_ARRAY){
var hash=tempFile.readU32(offset);
var nextHash=hash;
var i=0;
while(nextHash===hash){
createHashInput(container, hashId+'['+i+']', S32, offset+i*8);
i++;
nextHash=tempFile.readU32(offset+i*8);
}
}else if(type===F32_ARRAY){
var hash=tempFile.readU32(offset);
var nextHash=hash;
var i=0;
while(nextHash===hash){
createHashInput(container, hashId+'['+i+']', F32, offset+i*8);
i++;
nextHash=tempFile.readU32(offset+i*8);
}
}else if(type===VECTOR2F_ARRAY){
var hash=tempFile.readU32(offset);
var nextHash=hash;
var i=0;
while(nextHash===hash){
createHashInput(container, hashId+'['+i+']', VECTOR2F, offset+i*16);
i++;
nextHash=tempFile.readU32(offset+i*16);
}
}else if(type===VECTOR3F_ARRAY){
var hash=tempFile.readU32(offset);
var nextHash=hash;
var i=0;
while(nextHash===hash){
createHashInput(container, hashId+'['+i+']', VECTOR3F, offset+i*24);
i++;
nextHash=tempFile.readU32(offset+i*24);
}
}else if(type===STRING64_ARRAY){
var hash=tempFile.readU32(offset);
var nextHash=hash;
var i=0;
while(nextHash===hash){
createHashInput(container, hashId+'['+i+']', STRING64, offset+i*128);
i++;
nextHash=tempFile.readU32(offset+i*128);
}
}else{
addEditorRow(container, hashId+' ('+DATA_TYPES[type]+')');
}
}
function setBoolean(){
SavegameEditor._writeBoolean(this.offset, this.checked, 0);
}
function setS32(){
SavegameEditor._writeValue(this.offset, this.value, 0);
}
function setF32(){
SavegameEditor._writeFloat32(this.offset, this.value, 0);
}
function setString(){
SavegameEditor._writeString(this.offset, this.value);
}
function setString64(){
SavegameEditor._writeString64(this.offset, this.value);
}
function onScroll(){
var h=document.getElementById('header-top').getBoundingClientRect().height;
if(window.scrollY>h){
document.getElementById('header').style.position='fixed';
document.getElementById('header').style.top='-'+h+'px';
}else{
document.getElementById('header').style.position='absolute';
document.getElementById('header').style.top='0px';
}
}
window.addEventListener('scroll', onScroll, false);

View File

@ -30,17 +30,20 @@ caches.keys().then(function(cacheNames){
});
var PRECACHE_ID='zelda-botw-editor';
var PRECACHE_VERSION='v2b';
var PRECACHE_VERSION='v3';
var PRECACHE_URLS=[
//is hashes file too big for cacheing?
'/savegame-editors/zelda-botw/','/savegame-editors/zelda-botw/index.html',
'/savegame-editors/zelda-botw/zelda-botw.css',
'/savegame-editors/zelda-botw/zelda-botw.js',
'/savegame-editors/zelda-botw/zelda-botw.data.js',
'/savegame-editors/zelda-botw/zelda-botw.icons.js',
'/savegame-editors/zelda-botw/zelda-botw.locations.js',
'/savegame-editors/zelda-botw/zelda-botw.master.js',
'/savegame-editors/zelda-botw/favicon.png',
'/savegame-editors/zelda-botw/assets/_blank.png',
'/savegame-editors/zelda-botw/assets/logo.png',
'/savegame-editors/zelda-botw/assets/tabs.png',
'/savegame-editors/zelda-botw/assets/bg_black.jpg',
'/savegame-editors/zelda-botw/assets/bg_white.jpg',
'/savegame-editors/savegame-editor.js'

BIN
zelda-botw/assets/tabs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -13,7 +13,7 @@
<script type="text/javascript" src="./zelda-botw.data.js"></script>
<script type="text/javascript" src="./zelda-botw.locations.js"></script>
<script type="text/javascript" src="./zelda-botw.icons.js"></script>
<!-- <script type="text/javascript" src="./zelda-botw.hashes.js"></script> -->
<script type="text/javascript" src="./zelda-botw.master.js"></script>
<script type="text/javascript"><!--
/* service worker */
var FORCE_HTTPS=true;
@ -43,7 +43,18 @@
<div id="toolbar" class="hidden padding-vertical">
<div class="row wrapper">
<div class="twelve columns text-center">
<span class="clickable" onclick="SavegameEditor.changeEndianess()" id="span-version"></span> | <button class="with-icon icon1" onclick="SavegameEditor.addItem()">Add item</button>
<span class="clickable" onclick="SavegameEditor.changeEndianess()" id="span-version"></span>
|
<button id="tab-button-home" title="Home" class="tab-button active" onclick="showTab('home')"><i class="tab-icon home"></i></button>
<button id="tab-button-weapons" title="Weapons" class="tab-button" onclick="showTab('weapons')"><i class="tab-icon weapons"></i></button>
<button id="tab-button-bows" title="Bows" class="tab-button" onclick="showTab('bows')"><i class="tab-icon bows"></i></button>
<button id="tab-button-shields" title="Shields" class="tab-button" onclick="showTab('shields')"><i class="tab-icon shields"></i></button>
<button id="tab-button-clothes" title="Clothes" class="tab-button" onclick="showTab('clothes')"><i class="tab-icon clothes"></i></button>
<button id="tab-button-materials" title="Materials" class="tab-button" onclick="showTab('materials')"><i class="tab-icon materials"></i></button>
<button id="tab-button-food" title="Food" class="tab-button" onclick="showTab('food')"><i class="tab-icon food"></i></button>
<button id="tab-button-other" title="Other" class="tab-button" onclick="showTab('other')"><i class="tab-icon other"></i></button>
<button id="tab-button-horses" title="Horses" class="tab-button" onclick="showTab('horses')"><i class="tab-icon horses"></i></button>
<button id="tab-button-master" title="Master editor" class="tab-button" onclick="showTab('master')"><i class="tab-icon master"></i></button>
| <button class="button with-icon icon3" onclick="closeFile()">Close file</button>
<button class="button colored blue with-icon icon9" onclick="saveChanges()">Save changes</button>
</div>
@ -51,200 +62,269 @@
</div>
</div>
<!-- THE EDITOR -->
<div id="the-editor" class="wrapper hidden">
<!-- DEBUG -->
<div id="debug"></div>
<!-- RUPEES -->
<h3 class="border-red">Stats</h3>
<div class="row">
<div class="ten columns"><label for="number-rupees">Rupees</label></div>
<div class="two columns"><input id="number-rupees" class="full-width" type="text" /></div>
</div>
<div class="row">
<div class="ten columns"><label for="number-mons">Mons</label></div>
<div class="two columns"><input id="number-mons" class="full-width" type="text" /></div>
</div>
<div class="row">
<div class="ten columns"><label for="number-relic-gerudo">Gerudo relic remaining uses</label></div>
<div class="two columns text-right"><input id="number-relic-gerudo" class="small" type="text" /></div>
</div>
<div class="row">
<div class="ten columns"><label for="number-relic-goron">Goron relic remaining uses</label></div>
<div class="two columns text-right"><input id="number-relic-goron" class="small" type="text" /></div>
</div>
<div class="row">
<div class="ten columns"><label for="number-relic-rito">Rito relic remaining uses</label></div>
<div class="two columns text-right"><input id="number-relic-rito" class="small" type="text" /></div>
</div>
<div class="row" id="row-motorcycle">
<div class="ten columns"><label for="checkbox-motorcycle">Motorcycle</label></div>
<div class="two columns text-right"><input id="checkbox-motorcycle" type="checkbox" value="1" /></div>
</div>
<div class="row">
<div class="ten columns"><label for="number-playtime">Playtime</label></div>
<div class="two columns"><input type="text" id="number-playtime" class="text-right full-width" disabled /></div>
</div>
<div class="row">
<div class="ten columns"><label for="select-max-hearts">Max. hearts</label></div>
<div class="two columns">
<select id="select-max-hearts" class="full-width">
<option value="4">1</option>
<option value="8">2 hearts</option>
<option value="12">3 hearts</option>
<option value="16">4 hearts</option>
<option value="20">5 hearts</option>
<option value="24">6 hearts</option>
<option value="28">7 hearts</option>
<option value="32">8 hearts</option>
<option value="36">9 hearts</option>
<option value="40">10 hearts</option>
<option value="44">11 hearts</option>
<option value="48">12 hearts</option>
<option value="52">13 hearts</option>
<option value="56">14 hearts</option>
<option value="60">15 hearts</option>
<option value="64">16 hearts</option>
<option value="68">17 hearts</option>
<option value="72">18 hearts</option>
<option value="76">19 hearts</option>
<option value="80">20 hearts</option>
<option value="84">21 hearts</option>
<option value="88">22 hearts</option>
<option value="92">23 hearts</option>
<option value="96">24 hearts</option>
<option value="100">25 hearts</option>
<option value="104">26 hearts</option>
<option value="108">27 hearts</option>
<option value="112">28 hearts</option>
<option value="116">29 hearts</option>
<option value="120">30 hearts</option>
</select>
<!-- TAB: HOME -->
<div id="tab-home">
<!-- RUPEES -->
<h3 class="border-red">Stats</h3>
<div class="row">
<div class="ten columns"><label for="number-rupees">Rupees</label></div>
<div class="two columns"><input id="number-rupees" class="full-width" type="text" /></div>
</div>
</div>
<div class="row">
<div class="ten columns"><label for="select-max-stamina">Max. stamina </label></div>
<div class="two columns">
<select id="select-max-stamina" class="full-width">
<option value="1148846080">1 wheel</option>
<option value="1150681088">1 wheel+1/5</option>
<option value="1152319488">1 wheel+2/5</option>
<option value="1153957888">1 wheel+3/5</option>
<option value="1155596288">1 wheel+4/5</option>
<option value="1157234688">2 wheels</option>
<option value="1158250496">2 wheels+1/5</option>
<option value="1159069696">2 wheels+2/5</option>
<option value="1159888896">2 wheels+3/5</option>
<option value="1160708096">2 wheels+4/5</option>
<option value="1161527296">3 wheels</option>
</select>
<div class="row">
<div class="ten columns"><label for="number-mons">Mons</label></div>
<div class="two columns"><input id="number-mons" class="full-width" type="text" /></div>
</div>
<div class="row">
<div class="ten columns"><label for="number-relic-gerudo">Gerudo relic remaining uses</label></div>
<div class="two columns text-right"><input id="number-relic-gerudo" class="small" type="text" /></div>
</div>
<div class="row">
<div class="ten columns"><label for="number-relic-goron">Goron relic remaining uses</label></div>
<div class="two columns text-right"><input id="number-relic-goron" class="small" type="text" /></div>
</div>
<div class="row">
<div class="ten columns"><label for="number-relic-rito">Rito relic remaining uses</label></div>
<div class="two columns text-right"><input id="number-relic-rito" class="small" type="text" /></div>
</div>
<div class="row" id="row-motorcycle">
<div class="ten columns"><label for="checkbox-motorcycle">Motorcycle</label></div>
<div class="two columns text-right"><input id="checkbox-motorcycle" type="checkbox" value="1" /></div>
</div>
<div class="row">
<div class="ten columns"><label for="number-playtime">Playtime</label></div>
<div class="two columns"><input type="text" id="number-playtime" class="text-right full-width" disabled /></div>
</div>
<div class="row">
<div class="ten columns"><label for="select-max-hearts">Max. hearts</label></div>
<div class="two columns">
<select id="select-max-hearts" class="full-width">
<option value="4">1</option>
<option value="8">2 hearts</option>
<option value="12">3 hearts</option>
<option value="16">4 hearts</option>
<option value="20">5 hearts</option>
<option value="24">6 hearts</option>
<option value="28">7 hearts</option>
<option value="32">8 hearts</option>
<option value="36">9 hearts</option>
<option value="40">10 hearts</option>
<option value="44">11 hearts</option>
<option value="48">12 hearts</option>
<option value="52">13 hearts</option>
<option value="56">14 hearts</option>
<option value="60">15 hearts</option>
<option value="64">16 hearts</option>
<option value="68">17 hearts</option>
<option value="72">18 hearts</option>
<option value="76">19 hearts</option>
<option value="80">20 hearts</option>
<option value="84">21 hearts</option>
<option value="88">22 hearts</option>
<option value="92">23 hearts</option>
<option value="96">24 hearts</option>
<option value="100">25 hearts</option>
<option value="104">26 hearts</option>
<option value="108">27 hearts</option>
<option value="112">28 hearts</option>
<option value="116">29 hearts</option>
<option value="120">30 hearts</option>
</select>
</div>
</div>
<div class="row">
<div class="ten columns"><label for="select-max-stamina">Max. stamina </label></div>
<div class="two columns">
<select id="select-max-stamina" class="full-width">
<option value="1148846080">1 wheel</option>
<option value="1150681088">1 wheel+1/5</option>
<option value="1152319488">1 wheel+2/5</option>
<option value="1153957888">1 wheel+3/5</option>
<option value="1155596288">1 wheel+4/5</option>
<option value="1157234688">2 wheels</option>
<option value="1158250496">2 wheels+1/5</option>
<option value="1159069696">2 wheels+2/5</option>
<option value="1159888896">2 wheels+3/5</option>
<option value="1160708096">2 wheels+4/5</option>
<option value="1161527296">3 wheels</option>
</select>
</div>
</div>
<!-- Coordinates (Requires a memory editor) -->
<h3 class="border-green">Coordinates</h3>
<div class="row">
<div class="six columns"><label for="float-pos-x">Current Link coordinates (XYZ)</label></div>
<div class="two columns"><input id="float-pos-x" onchange="guessMainFieldGrid()" class="full-width" type="text" /></div>
<div class="two columns"><input id="float-pos-y" onchange="guessMainFieldGrid()" class="full-width" type="text" /></div>
<div class="two columns"><input id="float-pos-z" onchange="guessMainFieldGrid()" class="full-width" type="text" /></div>
</div>
<div class="row">
<div class="six columns"><label for="select-pos-maptype">Map</label></div>
<div class="three columns"><select id="select-pos-maptype"></select></div>
<div class="three columns"><select id="select-pos-map"></select></div>
</div>
<!-- COMPLETIONISM -->
<h3 class="border-blue">Completionism</h3>
<div class="row">
<div class="seven columns"><label for="number-koroks">Korok seeds</label></div>
<div class="five columns text-right">
<input type="text" id="number-koroks" style="width:50px" disabled />
<button onclick="unlockKoroks()">Get all</button>
<button onclick="addKoroksToMap()">Add pins to Map</button>
</div>
</div>
<div class="row">
<div class="seven columns"><label for="number-defeated-hinox">Defeated Hinox</label></div>
<div class="five columns text-right">
<input type="text" id="number-defeated-hinox" style="width:50px" disabled />
<button onclick="defeatAllHinox()">Defeat all</button>
<button onclick="addHinoxToMap()">Add pins to Map</button>
</div>
</div>
<div class="row">
<div class="seven columns"><label for="number-defeated-talus">Defeated Talus</label></div>
<div class="five columns text-right">
<input type="text" id="number-defeated-talus" style="width:50px" disabled />
<button onclick="defeatAllTalus()">Defeat all</button>
<button onclick="addTalusToMap()">Add pins to Map</button>
</div>
</div>
<div class="row">
<div class="seven columns"><label for="number-defeated-molduga">Defeated Molduga</label></div>
<div class="five columns text-right">
<input type="text" id="number-defeated-molduga" style="width:50px" disabled />
<button onclick="defeatAllMolduga()">Defeat all</button>
<button onclick="addMoldugaToMap()">Add pins to Map</button>
</div>
</div>
<div class="row">
<div class="nine columns"><label for="number-defeated-molduga">Hyrule Compendium</label></div>
<div class="three columns text-right">
<button onclick="setCompendiumToStock()">Set to stock</button>
</div>
</div>
<div class="row">
<div class="seven columns">Visited locations</div>
<div class="five columns text-right">
<button onclick="visitAllLocations()">Visit all</button>
<button onclick="addLocationsToMap()">Add pins to Map</button>
</div>
</div>
<div class="row">
<div class="nine columns">Map Pins</div>
<div class="three columns text-right">
<input type="text" id="number-map-pins" style="width:50px" disabled />
<button onclick="clearMapPins()">Clear</button>
</div>
</div>
</div>
<!-- Coordinates (Requires a memory editor) -->
<h3 class="border-green">Coordinates</h3>
<div class="row">
<div class="six columns"><label for="float-pos-x">Current Link coordinates (XYZ)</label></div>
<div class="two columns"><input id="float-pos-x" onchange="guessMainFieldGrid()" class="full-width" type="text" /></div>
<div class="two columns"><input id="float-pos-y" onchange="guessMainFieldGrid()" class="full-width" type="text" /></div>
<div class="two columns"><input id="float-pos-z" onchange="guessMainFieldGrid()" class="full-width" type="text" /></div>
<!-- TAB: WEAPONS -->
<div id="tab-weapons">
<h3>Weapons</h3><div id="container-weapons"></div>
</div>
<div class="row">
<div class="six columns"><label for="select-pos-maptype">Map</label></div>
<div class="three columns"><select id="select-pos-maptype"></select></div>
<div class="three columns"><select id="select-pos-map"></select></div>
<!-- TAB: BOWS -->
<div id="tab-bows">
<h3>Bows</h3><div id="container-bows"></div>
</div>
<!-- ITEMS -->
<h3>Weapons</h3><div id="container-weapons"></div>
<h3>Bows</h3><div id="container-bows"></div>
<h3>Shields</h3><div id="container-shields"></div>
<h3>Clothes</h3><div id="container-clothes"></div>
<h3>Materials</h3><div id="container-materials"></div>
<h3>Food</h3><div id="container-food"></div>
<h3>Other</h3><div id="container-other"></div>
<!-- HORSES -->
<h3 class="border-blue">Horses</h3>
<div class="row">
<div class="four columns"><button class="with-icon icon10" onclick="SavegameEditor.editHorse(0)">Edit horse 0</button></div>
<div class="four columns"><button class="with-icon icon10" onclick="SavegameEditor.editHorse(1)">Edit horse 1</button></div>
<div class="four columns"><button class="with-icon icon10" onclick="SavegameEditor.editHorse(2)">Edit horse 2</button></div>
<div class="four columns"><button class="with-icon icon10" onclick="SavegameEditor.editHorse(3)">Edit horse 3</button></div>
<div class="four columns"><button class="with-icon icon10" onclick="SavegameEditor.editHorse(4)">Edit horse 4</button></div>
<div class="four columns"><button class="with-icon icon10" onclick="SavegameEditor.editHorse(5)">Edit untamed horse</button></div>
</div>
<div class="row">
<div class="six columns"><label for="float-pos-x-horse">Current horse coordinates (XYZ)</label></div>
<div class="two columns"><input id="float-pos-x-horse" class="full-width" type="text" /></div>
<div class="two columns"><input id="float-pos-y-horse" class="full-width" type="text" /></div>
<div class="two columns"><input id="float-pos-z-horse" class="full-width" type="text" /></div>
<!-- TAB: SHIELDS -->
<div id="tab-shields">
<h3>Shields</h3><div id="container-shields"></div>
</div>
<!-- TAB: CLOTHES -->
<div id="tab-clothes">
<h3>Clothes</h3><div id="container-clothes"></div>
</div>
<!-- COMPLETIONISM -->
<h3 class="border-green">Completionism</h3>
<div class="row">
<div class="seven columns"><label for="number-koroks">Korok seeds</label></div>
<div class="five columns text-right">
<input type="text" id="number-koroks" style="width:50px" disabled />
<button onclick="unlockKoroks()">Get all</button>
<button onclick="addKoroksToMap()">Add pins to Map</button>
<!-- TAB: MATERIALS -->
<div id="tab-materials">
<h3>Materials</h3><div id="container-materials"></div>
</div>
<!-- TAB: FOOD -->
<div id="tab-food">
<h3>Food</h3><div id="container-food"></div>
</div>
<!-- TAB: OTHER -->
<div id="tab-other">
<h3>Other</h3><div id="container-other"></div>
</div>
<!-- ADD ITEM BUTTON -->
<div id="add-item-button" class="text-center">
<button class="with-icon icon1" onclick="SavegameEditor.addItem()">Add item</button>
</div>
<!-- TAB: HORSES -->
<div id="tab-horses">
<h3 class="border-blue">Horses</h3>
<div class="row">
<div class="twelve columns"><button class="with-icon icon10" onclick="SavegameEditor.editHorse(0)">Edit horse 0</button></div>
<div class="twelve columns"><button class="with-icon icon10" onclick="SavegameEditor.editHorse(1)">Edit horse 1</button></div>
<div class="twelve columns"><button class="with-icon icon10" onclick="SavegameEditor.editHorse(2)">Edit horse 2</button></div>
<div class="twelve columns"><button class="with-icon icon10" onclick="SavegameEditor.editHorse(3)">Edit horse 3</button></div>
<div class="twelve columns"><button class="with-icon icon10" onclick="SavegameEditor.editHorse(4)">Edit horse 4</button></div>
<div class="twelve columns"><button class="with-icon icon10" onclick="SavegameEditor.editHorse(5)">Edit untamed horse</button></div>
</div>
<div class="row">
<div class="six columns"><label for="float-pos-x-horse">Current horse coordinates (XYZ)</label></div>
<div class="two columns"><input id="float-pos-x-horse" class="full-width" type="text" /></div>
<div class="two columns"><input id="float-pos-y-horse" class="full-width" type="text" /></div>
<div class="two columns"><input id="float-pos-z-horse" class="full-width" type="text" /></div>
</div>
</div>
<div class="row">
<div class="seven columns"><label for="number-defeated-hinox">Defeated Hinox</label></div>
<div class="five columns text-right">
<input type="text" id="number-defeated-hinox" style="width:50px" disabled />
<button onclick="defeatAllHinox()">Defeat all</button>
<button onclick="addHinoxToMap()">Add pins to Map</button>
</div>
</div>
<div class="row">
<div class="seven columns"><label for="number-defeated-talus">Defeated Talus</label></div>
<div class="five columns text-right">
<input type="text" id="number-defeated-talus" style="width:50px" disabled />
<button onclick="defeatAllTalus()">Defeat all</button>
<button onclick="addTalusToMap()">Add pins to Map</button>
</div>
</div>
<div class="row">
<div class="seven columns"><label for="number-defeated-molduga">Defeated Molduga</label></div>
<div class="five columns text-right">
<input type="text" id="number-defeated-molduga" style="width:50px" disabled />
<button onclick="defeatAllMolduga()">Defeat all</button>
<button onclick="addMoldugaToMap()">Add pins to Map</button>
</div>
</div>
<div class="row">
<div class="nine columns"><label for="number-defeated-molduga">Hyrule Compendium</label></div>
<div class="three columns text-right">
<button onclick="setCompendiumToStock()">Set to stock</button>
</div>
</div>
<!-- TAB: MASTER EDITOR -->
<div id="tab-master">
<div id="master-editor-loading" class="text-center">Master editor is loading...</div>
<div id="master-editor-hidden" class="hidden">
<label for="select-filters">Filter: </label>
<select id="select-filters" onchange="BOTWMasterEditor.refreshResults()">
<option value="">- All -</option>
<option value="WolfLink_|Amiibo">Amiibo</option>
<option value="_DispNameFlag$">Display flag names</option>
<option value="100enemy">DLC1</option>
<option value="Motorcycle">DLC2</option>
<option value="Horse_">Horses</option>
<option value="Defeat_Enemy_|Defeated.+Num">Defeated enemies</option>
<option value="Porch|Cook">Items</option>
<option value="IsGet_">Get flags</option>
<option value="HiddenKorok|OldKorok_">Korok</option>
<option value="^Location_">Visited locations</option>
<option value="AlbumPicture|PictureBook">Compendium</option>
</select>
<input id="input-custom-filter" type="text" placeholder="Search hash keys" onchange="BOTWMasterEditor.refreshResults()" />
| <label for="select-page">Page: </label>
<button id="page-prev" onclick="BOTWMasterEditor.prevPage()">&laquo;</button>
<select id="select-page" class="small" onchange="BOTWMasterEditor.setPage(this.selectedIndex)"></select>
<button id="page-next" onclick="BOTWMasterEditor.nextPage()">&raquo;</button>
<div class="row">
<div class="seven columns">Visited locations</div>
<div class="five columns text-right">
<button onclick="visitAllLocations()">Visit all</button>
<button onclick="addLocationsToMap()">Add pins to Map</button>
</div>
</div>
<div class="row">
<div class="nine columns">Map Pins</div>
<div class="three columns text-right">
<input type="text" id="number-map-pins" style="width:50px" disabled />
<button onclick="clearMapPins()">Clear</button>
<table id="table"></table>
</div>
</div>
</div>
</div>
<!-- DIALOGS -->
<div id="dialog-horse" class="dialog">
<div id="row-tamed-horse">
@ -270,6 +350,5 @@
</div>
</div>
<ul id="caca"></ul>
</body>
</html>

View File

@ -1,4 +1,4 @@
/* Zelda BOTW Savegame editor by Marc Robledo v20170521 */
/* Zelda BOTW Savegame editor by Marc Robledo v20200215 */
/* minify at https://cssminifier.com/ + https://www.base64-image.de/ (sprites */
/* @FONT-FACES */
@ -14,6 +14,18 @@ body{
background-image:url(assets/bg_black.jpg);
}
/* master editor */
#toolbar select{width:initial !important}
#page-prev,#page-next{min-width:initial !important}
table{
border-collapse:collapse;
}
tr{border-bottom:1px solid #452e2e;height:36px}
tr:last-child{border-bottom:none}
tr:hover{background-color:#250e0e}
/* flex box */
.row{
display:flex;
@ -137,7 +149,32 @@ span.sprite.github{background-position:0px -48px;width:16px;height:16px; margin-
span.sprite.heart{background-position:-16px -48px;width:16px;height:16px; margin-right:5px}
button.with-icon.file-load:before{background-position:-32px -48px;width:20px;height:20px; margin-right:8px}
.tab-button{
padding:2px;
margin:0 2px;
min-width:1px;
line-height:0;
}
.tab-button.active{
border-color:#d3af61;
background-color: white;
}
i.tab-icon{
display:inline-block;
width:32px;height:32px;
background-image:url('assets/tabs.png');
background-size:320px;
}
i.tab-icon.home{background-position-x:-0px;}
i.tab-icon.weapons{background-position-x:-32px;}
i.tab-icon.bows{background-position-x:-64px;}
i.tab-icon.shields{background-position-x:-96px;}
i.tab-icon.clothes{background-position-x:-128px;}
i.tab-icon.materials{background-position-x:-160px;}
i.tab-icon.food{background-position-x:-192px;}
i.tab-icon.other{background-position-x:-224px;}
i.tab-icon.horses{background-position-x:-256px;}
i.tab-icon.master{background-position-x:-288px;}
@ -230,7 +267,7 @@ h3{
}
table{width:100%}
tbody tr:nth-child(even){background-color:#f2f2f2}
/*tbody tr:nth-child(even){background-color:#f2f2f2}*/
th{background-color:#d4d4d4}
@ -299,7 +336,8 @@ button{
box-shadow:0px 1px 0px rgba(255, 255, 255, 0.2) inset;
transition:border-color ease-in-out .15s;
box-sizing:border-box
box-sizing:border-box;
vertical-align:middle;
}
button.small{
min-width:1px
@ -308,7 +346,7 @@ button:hover{
text-shadow:none;
border-color:#999999
}
button:active{
button:active,button.active{
background-image:none;
transform:translate(0px,1px);
border-color:#888;
@ -565,12 +603,16 @@ button.no-text.with-icon:before{margin-right:0px}
transition:visibility 0s .35s,opacity .35s;
font-size:80%;
}
.tooltip.dark{
background-color:#333;
color:#eee
}
/* separation */
.tooltip.position-up{margin-bottom:10px}
.tooltip.position-down{margin-top:10px}
.tooltip.position-left{margin-right:10px}
.tooltip.position-right{margin-left:10px}
.tooltip.position-up{margin-bottom:8px}
.tooltip.position-down{margin-top:8px}
.tooltip.position-left{margin-right:8px}
.tooltip.position-right{margin-left:8px}
/* animation */
.tooltip.visible{visibility:visible;opacity:1;transition-delay:0s} /* transition-delay fixes fade-in/fade-out in some browsers */
@ -579,20 +621,36 @@ button.no-text.with-icon:before{margin-right:0px}
text-align:right;
}
.arrow{
width:0;height:0;
position:absolute;
}
/* arrow */
.tooltip:before{width:0;height:0;position:absolute;content:""}
.tooltip.position-down:before{top:-4px;border-bottom:5px solid #eee;border-left:5px solid transparent;border-right:5px solid transparent}
.tooltip.position-up:before{bottom:-4px;border-top:5px solid #eee;border-left:5px solid transparent;border-right:5px solid transparent}
.tooltip.position-left:before{right:-4px;border-left: 5px solid #eee;border-top:5px solid transparent;border-bottom: 5px solid transparent}
.tooltip.position-right:before{left:-4px;border-right:5px solid #eee;border-top: 5px solid transparent;border-bottom: 5px solid transparent}
.tooltip.position-vertical.align-left:before{left:4px}
.tooltip.position-vertical.align-center:before{left:50%;margin-left:-4px}
.tooltip.position-vertical.align-right:before{right:4px}
.tooltip.position-horizontal.align-top:before{top:4px}
.tooltip.position-horizontal.align-center:before{top:50%;margin-top:-4px}
.tooltip.position-horizontal.align-bottom:before{bottom:4px}
.tooltip.dark.position-down:before{border-bottom:5px solid #333}
.tooltip.dark.position-up:before{border-top:5px solid #333}
.tooltip.dark.position-left:before{border-left: 5px solid #333}
.tooltip.dark.position-right:before{border-right:5px solid #333}
.tooltip.position-down .arrow{
.tooltip.position-down:before{
border-left:5px solid transparent;
border-right:5px solid transparent;
border-bottom:5px solid #eee;
top:-5px;
}
.tooltip.position-up .arrow{
.tooltip.position-up:before{
border-left:5px solid transparent;
border-right:5px solid transparent;

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
The legend of Zelda: Breath of the wild v20190625
The legend of Zelda: Breath of the wild v20200215
by Marc Robledo 2017-2019
*/
var currentEditingItem=0;
@ -12,15 +12,14 @@ SavegameEditor={
/* Constants */
Constants:{
MAX_ITEMS:410,
STRING_SIZE:0x80,
STRING_SIZE:0x20,
STRING64_SIZE:0x80,
//missing versions: 1.1.1, 1.1.2 and 1.4.1
VERSION: ['v1.0', 'v1.1', 'v1.2', 'v1.3', 'v1.3.1', 'Kiosk', 'v1.3.3','v1.3.4', 'v1.4', 'v1.5', 'v1.6', 'v1.6*', 'v1.6**','v1.6***'],
FILESIZE: [896976, 897160, 897112, 907824, 907824, 916576, 1020648, 1020648, 1027208, 1027208, 1027216, 1027216, 1027216, 1027216],
HEADER: [0x24e2, 0x24ee, 0x2588, 0x29c0, 0x2a46, 0x2f8e, 0x3ef8, 0x3ef9, 0x471a, 0x471b, 0x471e, 0x0f423d, 0x0f423e,0x0f423f],
VERSION: ['v1.0', 'v1.1', 'v1.2', 'v1.3', 'v1.3.1', 'Kiosk', 'v1.3.3','v1.3.4', 'v1.4', 'v1.5', 'v1.5*', 'v1.6', 'v1.6*', 'v1.6**','v1.6***'],
FILESIZE: [896976, 897160, 897112, 907824, 907824, 916576, 1020648, 1020648, 1027208, 1027208, 1027248, 1027216, 1027216, 1027216, 1027216],
HEADER: [0x24e2, 0x24ee, 0x2588, 0x29c0, 0x2a46, 0x2f8e, 0x3ef8, 0x3ef9, 0x471a, 0x471b, 0x471b, 0x471e, 0x0f423d, 0x0f423e,0x0f423f],
MAP_ICONS: 0x9383490e,
MAP_POS: 0xea9def3f,
ICON_TYPES:{SWORD: 27, BOW:28, SHIELD:29, POT:30, STAR:31, CHEST:32,SKULL:33,LEAF:34,TOWER:35}
},
@ -44,6 +43,7 @@ SavegameEditor={
0x73c29681, 'PLAYTIME',
0x7b74e117, 'HORSE_NAMES',
0x8a94e07a, 'KOROK_SEED_COUNTER',
0x9383490e, 'MapApp_MapIconNo',
0x97f925c3, 'RELIC_GERUDO',
0x982ba201, 'HORSE_POSITION',
0x9c6cfd3f, 'HORSE_MANES',
@ -55,27 +55,24 @@ SavegameEditor={
0xce7afed3, 'MONS',
0xd913b769, 'MAPTYPE',
0xe1a0ca54, 'HORSE_BONDS', /* max=0x3f80 */
0xea9def3f, 'MapApp_MapIconPos',
0xf1cf4807, 'RELIC_GORON',
0xfda0cde4, 'RELIC_RITO'
0xfda0cde4, 'RELIC_RITO'
],
Headers:{
'MapApp_MapIconNo':0x9383490e,
'MapApp_MapIconPos':0xea9def3f
},
/* private functions */
_toHexInt:function(i){var s=i.toString(16);while(s.length<8)s='0'+s;return '0x'+s},
_writeBoolean:function(offset,val,arrayPos){if(arrayPos)tempFile.writeU32(offset+8*i,val?1:0);else tempFile.writeU32(offset,val?1:0)},
_writeValue:function(offset,val,arrayPos){if(arrayPos)tempFile.writeU32(offset+8*i,val);else tempFile.writeU32(offset,val)},
_writeString:function(offset,str){
for(var i=0; i<16; i++){
tempFile.writeBytes(offset,[0,0,0,0]);
var fourBytes=str.substr(i*4, 4);
for(j=0; j<fourBytes.length; j++){
tempFile.writeU8(offset+j, fourBytes.charCodeAt(j));
}
offset+=8;
}
},
_writeStringShort:function(offset,str){
for(var i=0; i<8; i++){
_writeBoolean:function(offset,val,arrayPos){if(arrayPos)tempFile.writeU32(offset+8*arrayPos,val?1:0);else tempFile.writeU32(offset,val?1:0)},
_writeValue:function(offset,val,arrayPos){if(arrayPos)tempFile.writeU32(offset+8*arrayPos,val);else tempFile.writeU32(offset,val)},
_writeFloat32:function(offset,val,arrayPos){if(arrayPos)tempFile.writeF32(offset+8*arrayPos,val);else tempFile.writeF32(offset,val)},
_writeString:function(offset,str,len){
len=len || 8;
for(var i=0; i<len; i++){
tempFile.writeBytes(offset,[0,0,0,0]);
var fourBytes=str.substr(i*4, 4);
for(j=0; j<fourBytes.length; j++){
@ -84,6 +81,8 @@ SavegameEditor={
offset+=8;
}
},
_writeString64:function(offset,str){this._writeString(offset,str, 16);},
_writeString256:function(offset,str){this._writeString(offset,str, 64);},
_searchHash:function(hash){
for(var i=0x0c; i<tempFile.fileSize; i+=8)
@ -103,7 +102,7 @@ SavegameEditor={
this._writeValue(offset+4,val);
},
_getOffsets:function(v){
_getOffsets:function(){
this.Offsets={};
var startSearchOffset=0x0c;
for(var i=0; i<this.Hashes.length; i+=2){
@ -134,28 +133,27 @@ SavegameEditor={
return 'other'
},
_readString:function(offset){
_readString:function(offset, len){
len=len || 8;
var txt='';
for(var j=0; j<16; j++){
for(var j=0; j<len; j++){
txt+=tempFile.readString(offset,4);
offset+=8;
}
return txt
},
_readStringShort:function(offset){
var txt='';
for(var j=0; j<8; j++){
txt+=tempFile.readString(offset,4);
offset+=8;
}
return txt
_readString64:function(offset){
return this._readString(offset, 16);
},
_readString256:function(offset){
return this._readString(offset, 64);
},
_loadItemName:function(i){
return this._readString(this.Offsets.ITEMS+i*0x80);
return this._readString64(this.Offsets.ITEMS+i*0x80);
},
_writeItemName:function(i,newItemNameId){
this._writeString(this.Offsets.ITEMS+i*0x80, newItemNameId);
this._writeString64(this.Offsets.ITEMS+i*0x80, newItemNameId);
},
_getItemMaximumQuantity:function(itemId){
var cat=this._getItemCategory(itemId);
@ -232,7 +230,13 @@ SavegameEditor={
i++;
}
if(i<this.Constants.MAX_ITEMS){
this.selectItem.selectedIndex++;
if(this._getItemCategory(this.selectItem.value)===currentTab){
this.selectItem.selectedIndex++;
if(this._getItemCategory(this.selectItem.value)!==currentTab)
this.selectItem.value=this.selectItem.categories[currentTab].children[0].value;
}else{
this.selectItem.value=this.selectItem.categories[currentTab].children[0].value;
}
var itemNameId=this.selectItem.value;
this._writeItemName(i,itemNameId);
var row=this._createItemRow(i, false);
@ -259,6 +263,7 @@ SavegameEditor={
var row=this._getItemRow(i);
row.parentElement.removeChild(row);
document.getElementById('container-'+newCat).appendChild(row);
showTab(newCat);
(row.previousElementSibling || row).scrollIntoView({block:'start', behavior:'smooth'});
}
this._writeItemName(i, nameId);
@ -294,7 +299,7 @@ SavegameEditor={
currentEditingItem=i;
if(currentEditingItem==5){ /* untamed horse */
hide('row-tamed-horse');
if(!this._readString(this.Offsets.HORSE_TYPES+this.Constants.STRING_SIZE*5).startsWith('GameRomHorse')){
if(!this._readString64(this.Offsets.HORSE_TYPES+this.Constants.STRING64_SIZE*5).startsWith('GameRomHorse')){
MarcDialogs.alert('Error: this will only work if your savegame has Link on an untamed horse.');
return false;
}
@ -302,25 +307,25 @@ SavegameEditor={
getField('horse-type').children[28].disabled=false;
}else{
show('row-tamed-horse');
setValue('horse-name',this._readString(this.Offsets.HORSE_NAMES+this.Constants.STRING_SIZE*i));
setValue('horse-saddles',this._readString(this.Offsets.HORSE_SADDLES+this.Constants.STRING_SIZE*i));
setValue('horse-reins',this._readString(this.Offsets.HORSE_REINS+this.Constants.STRING_SIZE*i));
setValue('horse-name',this._readString64(this.Offsets.HORSE_NAMES+this.Constants.STRING64_SIZE*i));
setValue('horse-saddles',this._readString64(this.Offsets.HORSE_SADDLES+this.Constants.STRING64_SIZE*i));
setValue('horse-reins',this._readString64(this.Offsets.HORSE_REINS+this.Constants.STRING64_SIZE*i));
getField('horse-type').children[27].disabled=true;
getField('horse-type').children[28].disabled=true;
}
setValue('horse-type',this._readString(this.Offsets.HORSE_TYPES+this.Constants.STRING_SIZE*i));
setValue('horse-type',this._readString64(this.Offsets.HORSE_TYPES+this.Constants.STRING64_SIZE*i));
MarcDialogs.open('horse');
},
editHorse2:function(i,name,saddles,reins,type){
if(currentEditingItem<5){
this._writeString(this.Offsets.HORSE_NAMES+this.Constants.STRING_SIZE*i, getValue('horse-name'));
this._writeString(this.Offsets.HORSE_SADDLES+this.Constants.STRING_SIZE*i, getValue('horse-saddles'));
this._writeString(this.Offsets.HORSE_REINS+this.Constants.STRING_SIZE*i, getValue('horse-reins'));
this._writeString64(this.Offsets.HORSE_NAMES+this.Constants.STRING64_SIZE*i, getValue('horse-name'));
this._writeString64(this.Offsets.HORSE_SADDLES+this.Constants.STRING64_SIZE*i, getValue('horse-saddles'));
this._writeString64(this.Offsets.HORSE_REINS+this.Constants.STRING64_SIZE*i, getValue('horse-reins'));
}
this._writeString(this.Offsets.HORSE_TYPES+this.Constants.STRING_SIZE*i, getValue('horse-type'));
this._writeString64(this.Offsets.HORSE_TYPES+this.Constants.STRING64_SIZE*i, getValue('horse-type'));
if(getValue('horse-type')==='GameRomHorse00L'){
this._writeString(this.Offsets.HORSE_MANES+this.Constants.STRING_SIZE*i, 'Horse_Link_Mane_00L');
this._writeString64(this.Offsets.HORSE_MANES+this.Constants.STRING64_SIZE*i, 'Horse_Link_Mane_00L');
}
},
@ -357,8 +362,14 @@ SavegameEditor={
this._getOffsets(i);
setValue('version', this.Constants.VERSION[i]+' ('+CONSOLE+')');
return true;
}else if((tempFile.fileSize>=896976 && tempFile.fileSize<=1500000) && versionHash===this.Constants.HEADER[i] && tempFile.readU32(4)===0xffffffff){ /* check for mods, filesizes vary */
this._getOffsets(i);
setValue('version', this.Constants.VERSION[i]+'<small>mod</small> ('+CONSOLE+')');
return true;
}
}
return false
},
@ -383,6 +394,7 @@ SavegameEditor={
setNumericRange('relic-rito', 0, 99);
/* prepare edit item selector */
this.selectItem.categories={};
for(var i=0; i<BOTW_Data.Translations.length; i++){
var optGroup=document.createElement('optgroup');
optGroup.label=BOTW_Data.Translations[i].id;
@ -390,10 +402,12 @@ SavegameEditor={
for(var item in BOTW_Data.Translations[i].items){
var opt=document.createElement('option');
opt.value=item;
opt.group=BOTW_Data.Translations[i].id;
opt.innerHTML=BOTW_Data.Translations[i].items[item];
optGroup.appendChild(opt);
}
this.selectItem.appendChild(optGroup);
this.selectItem.categories[BOTW_Data.Translations[i].id]=optGroup;
}
this.selectItem.value='Armor_180_Lower';
@ -450,6 +464,10 @@ SavegameEditor={
select('horse-saddles', this._arrayToSelectOpts(BOTW_Data.HORSE_SADDLES));
select('horse-reins', this._arrayToSelectOpts(BOTW_Data.HORSE_REINS));
select('horse-type', this._arrayToSelectOpts(BOTW_Data.HORSE_TYPES));
MarcTooltips.add('.tab-button',{className:'dark',fixed:true});
},
_timeToString:function(timeVal){
@ -496,8 +514,8 @@ SavegameEditor={
setValue('pos-y', tempFile.readF32(this.Offsets.PLAYER_POSITION+8));
setValue('pos-z', tempFile.readF32(this.Offsets.PLAYER_POSITION+16));
var map=this._readStringShort(this.Offsets.MAP);
var mapType=this._readStringShort(this.Offsets.MAPTYPE);
var map=this._readString(this.Offsets.MAP);
var mapType=this._readString(this.Offsets.MAPTYPE);
getField('pos-map').children[0].value=map;
getField('pos-map').children[0].innerHTML='* '+map+' *';
getField('pos-maptype').children[0].value=mapType;
@ -554,9 +572,9 @@ SavegameEditor={
}
}
MarcTooltips.add(document.querySelectorAll('#container-weapons input'),'Weapon durability',{position:'bottom',align:'right'});
MarcTooltips.add(document.querySelectorAll('#container-bows input'),'Bow durability',{position:'bottom',align:'right'});
MarcTooltips.add(document.querySelectorAll('#container-shields input'),'Shield durability',{position:'bottom',align:'right'});
MarcTooltips.add('#container-weapons input',{text:'Weapon durability',position:'bottom',align:'right'});
MarcTooltips.add('#container-bows input',{text:'Bow durability',position:'bottom',align:'right'});
MarcTooltips.add('#container-shields input',{text:'Shield durability',position:'bottom',align:'right'});
BOTW_Icons.startLoadingIcons();
/* modifier column */
@ -573,6 +591,8 @@ SavegameEditor={
additional.appendChild(inputNumber('modifier-'+modifierColumn+'s-value-'+i, 0, 0xffffffff, tempFile.readU32(this.Offsets['FLAGSV_'+modifierColumn.toUpperCase()]+i*8)));
}
}
showTab('home');
},
/* save function */
@ -605,8 +625,8 @@ SavegameEditor={
tempFile.writeF32(this.Offsets.PLAYER_POSITION+8, getValue('pos-y'));
tempFile.writeF32(this.Offsets.PLAYER_POSITION+16, getValue('pos-z'));
this._writeStringShort(this.Offsets.MAP, getValue('pos-map'))
this._writeStringShort(this.Offsets.MAPTYPE, getValue('pos-maptype'))
this._writeString(this.Offsets.MAP, getValue('pos-map'))
this._writeString(this.Offsets.MAPTYPE, getValue('pos-maptype'))
tempFile.writeF32(this.Offsets.HORSE_POSITION, getValue('pos-x-horse'));
tempFile.writeF32(this.Offsets.HORSE_POSITION+8, getValue('pos-y-horse'));
@ -637,6 +657,34 @@ SavegameEditor={
}
}
/* TABS */
var availableTabs=['home','weapons','bows','shields','clothes','materials','food','other','horses','master'];
var currentTab;
function showTab(newTab){
currentTab=newTab;
for(var i=0; i<availableTabs.length; i++){
document.getElementById('tab-button-'+availableTabs[i]).className=currentTab===availableTabs[i]?'tab-button active':'tab-button';
document.getElementById('tab-'+availableTabs[i]).style.display=currentTab===availableTabs[i]?'block':'none';
}
document.getElementById('add-item-button').style.display=(newTab==='home' || newTab==='horses' || newTab==='master')? 'none':'block';
if(newTab==='master'){
if(BOTWMasterEditor.isLoaded())
BOTWMasterEditor.refreshResults();
else
BOTWMasterEditor.loadHashes();
}
}
/*
function setValueByHash(hash, val){
var offset=SavegameEditor._searchHash(hash);
@ -646,7 +694,7 @@ function setValueByHash(hash, val){
SavegameEditor._writeValue(offset, val[1], 1);
SavegameEditor._writeValue(offset, val[2], 2);
}else if(typeof val==='string'){
SavegameEditor._writeString(offset, val);
SavegameEditor._writeString64(offset, val);
}else{
SavegameEditor._writeValue(offset, val);
}
@ -823,12 +871,12 @@ function clearMapPins(){
}
function iterateMapPins(f){
var offset = SavegameEditor._searchHash(SavegameEditor.Constants.MAP_ICONS)
var offset = SavegameEditor.Offsets.MapApp_MapIconNo;
for (var i = 0;; i++){
var base = offset + (8 * i)
var hdr = tempFile.readU32(base)
var val = tempFile.readU32(base + 4)
if (hdr != SavegameEditor.Constants.MAP_ICONS){
if (hdr != SavegameEditor.Headers.MapApp_MapIconNo){
break
}
if (!f(val,base+4)){
@ -837,12 +885,12 @@ function iterateMapPins(f){
}
}
function iterateMapPinLocations(f){
offset = SavegameEditor._searchHash(SavegameEditor.Constants.MAP_POS)
offset = SavegameEditor.Offsets.MapApp_MapIconPos;
for (var i = 0;; i++){
var base = offset + (8 * i)
var hdr = tempFile.readU32(base)
var val = tempFile.readF32(base + 4)
if (hdr != SavegameEditor.Constants.MAP_POS){
if (hdr != SavegameEditor.Headers.MapApp_MapIconPos){
break
}
if(!f(val,base+4)){
@ -945,9 +993,8 @@ function addLocationsToMap(){
}
/* MarcTooltips.js v20170518 - Marc Robledo 2014-2017 - http://www.marcrobledo.com/license */
var MarcTooltips=function(){return{add:function(a,b,c){var d=document.createElement("div");d.className="tooltip",d.style.position="absolute",d.style.zIndex="9000",d.style.top="0",d.style.left="0",d.innerHTML=b,document.body.appendChild(d);var e="down",f="center";c&&c.position&&/^(up|down|left|right)$/i.test(c.position)&&(e=c.position.toLowerCase()),c&&c.align&&/^(top|bottom|left|right)$/i.test(c.align)&&(("up"!==e&&"down"!==e||"left"!==c.align&&"right"!==c.align)&&("left"!==e&&"right"!==e||"top"!==c.align&&"bottom"!==c.align)||(f=c.align.toLowerCase()));var h=document.createElement("div");h.className="arrow",d.className+=" position-"+e+" align-"+f,d.className+="left"===e||"right"===e?" position-horizontal":" position-vertical",d.appendChild(h);var i=function(){var a=document.documentElement,b=(window.pageXOffset||a.scrollLeft)-(a.clientLeft||0),c=(window.pageYOffset||a.scrollTop)-(a.clientTop||0),g=this.getBoundingClientRect(),h=d.getBoundingClientRect();d.style.top="up"===e?parseInt(g.top+c-h.height)+"px":"down"===e?parseInt(g.top+c+g.height)+"px":"top"===f?parseInt(g.top+c)+"px":"bottom"===f?parseInt(g.top+c-(h.height-g.height))+"px":parseInt(g.top+c-parseInt((h.height-g.height)/2))+"px",d.style.left="up"===e||"down"===e?"left"===f?parseInt(g.left+b)+"px":"right"===f?parseInt(g.left+b-(h.width-g.width))+"px":parseInt(g.left+b-parseInt((h.width-g.width)/2))+"px":"left"===e?parseInt(g.left+b-h.width)+"px":parseInt(g.left+b+g.width)+"px",d.className+=" visible"},j=function(){d.className=d.className.replace(" visible","")};"string"==typeof a&&(a=[a]);for(var k=0;k<a.length;k++)if("string"==typeof a[k])if(/^#[0-9a-zA-Z_\-]+$/.test(a[k])){var l=document.getElementById(a[k].replace("#",""));l.addEventListener("mouseover",i,!1),l.addEventListener("mouseout",j,!1)}else for(var m=document.querySelectorAll(a[k]),n=0;n<m.length;n++)m[n].addEventListener("mouseover",i,!1),m[n].addEventListener("mouseout",j,!1);else a[k].addEventListener("mouseover",i,!1),a[k].addEventListener("mouseout",j,!1)}}}();
/* MarcTooltips.js v20200216 - Marc Robledo 2014-2020 - http://www.marcrobledo.com/license */
var MarcTooltips=function(){var n=/MSIE 8/.test(navigator.userAgent);function d(t,e,o){n?t.attachEvent("on"+e,o):t.addEventListener(e,o,!1)}function u(t){void 0!==t.stopPropagation?t.stopPropagation():t.cancelBubble=!0}function g(t){if(/^#[0-9a-zA-Z_\-]+$/.test(t))return[document.getElementById(t.replace("#",""))];var e=document.querySelectorAll(t);if(n){for(var o=[],i=0;i<e.length;i++)o.push(e[i]);return o}return Array.prototype.slice.call(e)}var h=function(t,e,o){t.className=t.className.replace(/position-\w+/,"position-"+e.position).replace(/align-\w+/,"align-"+e.align);var i=(window.pageXOffset||document.documentElement.scrollLeft)-(document.documentElement.clientLeft||0),n=(window.pageYOffset||document.documentElement.scrollTop)-(document.documentElement.clientTop||0);e.fixed&&(n=i=0);var l=t.attachedTo.getBoundingClientRect().left,a=t.attachedTo.getBoundingClientRect().top,s=t.attachedTo.offsetWidth,p=t.attachedTo.offsetHeight;if("up"===e.position?t.style.top=parseInt(a+n-t.offsetHeight)+"px":"down"===e.position?t.style.top=parseInt(a+n+p)+"px":"top"===e.align?t.style.top=parseInt(a+n)+"px":"bottom"===e.align?t.style.top=parseInt(a+n-(t.offsetHeight-p))+"px":t.style.top=parseInt(a+n-parseInt((t.offsetHeight-p)/2))+"px","up"===e.position||"down"===e.position?"left"===e.align?t.style.left=parseInt(l+i)+"px":"right"===e.align?t.style.left=parseInt(l+i-(t.offsetWidth-s))+"px":t.style.left=parseInt(l+i-parseInt((t.offsetWidth-s)/2))+"px":"left"===e.position?t.style.left=parseInt(l+i-t.offsetWidth)+"px":"right"===e.position&&(t.style.left=parseInt(l+i+s)+"px"),o){var r={position:e.position,align:e.align,fixed:e.fixed},c=parseInt(t.style.left.replace("px","")),f=parseInt(t.style.top.replace("px","")),d=c+t.offsetWidth,u=f+t.offsetHeight,g=(i=window.scrollX,n=window.scrollY,Math.max(document.documentElement.clientWidth,window.innerWidth||0)),m=Math.max(document.documentElement.clientHeight,window.innerHeight||0);"up"===e.position||"down"===e.position?(g<d?r.align="right":c<i&&(r.align="left"),f<n?r.position="down":n+m<u&&(r.position="up")):(m<u?r.align="bottom":f<n&&(r.align="top"),c<i?r.position="right":i+g<d&&(r.position="left")),h(t,r,!1)}},m={};d(window,"load",function(){d(n?document:window,"click",function(){for(key in m)/ visible$/.test(m[key].className)&&/:true:/.test(key)&&(m[key].className=m[key].className.replace(" visible",""))}),d(window,"resize",function(){for(key in m)/ visible$/.test(m[key].className)&&m[key].attachedTo&&h(m[key],m[key].tooltipInfo,!0)})});function y(t){var e=t.currentTarget||t.srcElement;e.title&&(e.setAttribute("data-tooltip",e.title),e.title=""),(e.tooltip.attachedTo=e).tooltip.innerHTML=e.getAttribute("data-tooltip"),e.tooltip.className+=" visible",h(e.tooltip,e.tooltip.tooltipInfo,!0)}function w(t){var e=t.currentTarget||t.srcElement;e.tooltip.className=e.tooltip.className.replace(" visible","")}return{add:function(t,e){var o="down",i="center",n=!1,l=!1,a=!1,s=!1,p=!1;e&&(e.position&&/^(up|down|left|right)$/i.test(e.position)&&(o=e.position.toLowerCase()),e.align&&/^(top|bottom|left|right)$/i.test(e.align)&&(("up"!==o&&"down"!==o||"left"!==e.align&&"right"!==e.align)&&("left"!==o&&"right"!==o||"top"!==e.align&&"bottom"!==e.align)||(i=e.align.toLowerCase())),l=e.clickable||e.onClick||e.onclick||!1,a=e.focusable||e.onFocus||e.onfocus||!1,s=e.fixed||e.positionFixed||!1,n=e.class||e.className||e.customClass||e.customClassName||!1,p=e.text||e.customText||!1);for(var r=function(t){if("string"==typeof t)return g(t);if(t.length){for(var e=[],o=0;o<t.length;o++)"string"==typeof t[o]?e=e.concat(g(t[o])):e.push(t[o]);return e}return[t]}(t),c=function(t,e,o,i,n){var l=t+":"+e+":"+o+":"+i;if(m[l])return m[l];var a=document.createElement("div");return a.className="tooltip position-"+t+" align-"+e,a.className+="left"===t||"right"===t?" position-horizontal":" position-vertical",i&&(a.className+=" "+i),a.style.position=n?"fixed":"absolute",a.style.zIndex="9000",a.style.top="0",a.style.left="0",a.attachedTo=null,a.tooltipInfo={position:t,align:e,fixed:n},o&&d(a,"click",u),m[l]=a,document.body.appendChild(a),a}(o,i,l||a,n,s),f=0;f<r.length;f++)p?r[f].setAttribute("data-tooltip",p):r[f].title&&r[f].setAttribute("data-tooltip",r[f].title),r[f].title="",r[f].tooltip=c,a?(d(r[f],"focus",y),d(r[f],"blur",w),d(r[f],"click",u)):l?(d(r[f],"click",y),d(r[f],"click",u)):(d(r[f],"mouseover",y),d(r[f],"mouseout",w))}}}();
function onScroll(){
var h=document.getElementById('header-top').getBoundingClientRect().height;
@ -970,4 +1017,28 @@ if(typeof String.startsWith==='undefined'){
String.prototype.startsWith=function(search){
return (new RegExp('^'+search)).test(this)
};
}
var masterModeLoaded=false;
function loadMasterMode(){
if(!masterModeLoaded){
var script=document.createElement('script');
script.type='text/javascript';
script.src='./zelda-botw.master.js';
script.onload=function(){
masterModeLoaded=true;
document.getElementById('tab-button-master').disabled=false;
//BOTWMasterEditor.prepare();
};
document.getElementsByTagName('head')[0].appendChild(script);
}
}

View File

@ -0,0 +1,295 @@
/*
The legend of Zelda: Breath of the wild - Master editor v20190625
by Marc Robledo 2017-2019
datamining by MrCheeze:
https://raw.githubusercontent.com/MrCheeze/botw-tools/master/gamedata.json
*/
const BOOL=1;
const BOOL_ARRAY=2;
const S32=3;
const S32_ARRAY=4;
const F32=5;
const F32_ARRAY=6;
const VECTOR2F=7;
const VECTOR2F_ARRAY=8;
const VECTOR3F=9;
const VECTOR3F_ARRAY=10;
const VECTOR4F=11;
const VECTOR4F_ARRAY=12;
const STRING=13;
const STRING_ARRAY=14;
const STRING64=15;
const STRING64_ARRAY=16;
const STRING256=17;
const STRING256_ARRAY=18;
function addEditorRow(container, left, right){
var tr=document.createElement('tr');
tr.appendChild(document.createElement('td'));
tr.appendChild(document.createElement('td'));
tr.children[1].className='text-right';
if(right){
tr.children[0].appendChild(label(right.id, left));
tr.children[1].appendChild(right);
}else{
tr.children[0].innerHTML=left;
}
container.appendChild(tr);
}
function createHashInput(container, hashId, type, offset){
if(type===BOOL){
var c=checkbox(hashId);
c.offset=offset+4;
c.addEventListener('change', setBoolean);
if(tempFile.readU32(offset+4))
c.checked=true;
addEditorRow(container, hashId, c);
return 8;
}else if(type===S32){
var inp=inputNumber(hashId, 0, 0xffffffff, tempFile.readU32(offset+4));
inp.offset=offset+4;
inp.addEventListener('change', setS32);
addEditorRow(container, hashId, inp);
return 8;
}else if(type===F32){
var inp=inputNumber(hashId, 0, 0xffffffff, tempFile.readF32(offset+4));
inp.offset=offset+4;
inp.addEventListener('change', setF32);
addEditorRow(container, hashId, inp);
return 8;
}else if(type===VECTOR2F){
createHashInput(container, hashId+'[x]', F32, offset);
createHashInput(container, hashId+'[y]', F32, offset+8);
return 16;
}else if(type===VECTOR3F){
createHashInput(container, hashId+'[x]', F32, offset);
createHashInput(container, hashId+'[y]', F32, offset+8);
createHashInput(container, hashId+'[z]', F32, offset+16);
return 24;
}else if(type===VECTOR4F){
createHashInput(container, hashId+'[x]', F32, offset);
createHashInput(container, hashId+'[y]', F32, offset+8);
createHashInput(container, hashId+'[z]', F32, offset+16);
createHashInput(container, hashId+'[t]', F32, offset+24);
return 32;
}else if(type===STRING){
var inp=input(hashId, SavegameEditor._readString(offset+4));
inp.offset=offset+4;
inp.maxLength=32;
inp.addEventListener('change', setString);
addEditorRow(container, hashId, inp);
return 0x20;
}else if(type===STRING64){
var inp=input(hashId, SavegameEditor._readString64(offset+4));
inp.offset=offset+4;
inp.maxLength=64;
inp.addEventListener('change', setString64);
addEditorRow(container, hashId, inp);
return 0x80;
}else if(type===STRING256){
var inp=input(hashId, SavegameEditor._readString256(offset+4));
inp.offset=offset+4;
inp.maxLength=256;
inp.addEventListener('change', setString256);
addEditorRow(container, hashId, inp);
return 0x0200;
}else if(type && type%2===0){ /* array */
var hash=tempFile.readU32(offset);
var nextHash=hash;
var i=0;
var size=0;
while(nextHash===hash){
size=createHashInput(container, hashId+'['+i+']', type-1, offset+i*size);
i++;
nextHash=tempFile.readU32(offset+i*size);
}
}else{
addEditorRow(container, hashId+' (unknown)');
}
}
function setBoolean(){
SavegameEditor._writeBoolean(this.offset, this.checked, 0);
}
function setS32(){
SavegameEditor._writeValue(this.offset, this.value, 0);
}
function setF32(){
SavegameEditor._writeFloat32(this.offset, this.value, 0);
}
function setString(){
SavegameEditor._writeString(this.offset, this.value);
}
function setString64(){
SavegameEditor._writeString64(this.offset, this.value);
}
function setString256(){
SavegameEditor._writeString256(this.offset, this.value);
}
var BOTWMasterEditor=(function(){
var HASHES_PER_PAGE=100;
var loaded=false;
var HASHES=[];
var parseHashFile=function(responseText){
var lines=responseText.split('\n');
for(var i=0; i<lines.length; i++){
var data=lines[i].split(';');
HASHES[parseInt(data[0])]=[
parseInt(data[1]),
data[2]
];
}
document.getElementById('master-editor-loading').style.display='none';
document.getElementById('master-editor-hidden').style.display='block';
BOTWMasterEditor.refreshResults();
};
return{
isLoaded:function(){
return loaded;
},
loadHashes:function(){
if(typeof window.fetch==='function'){
fetch('./zelda-botw.hashes.csv')
.then(res => res.text()) // Gets the response and returns it as a blob
.then(responseText => {
parseHashFile(responseText);
})
.catch(function(){
alert('Unexpected error: can\'t download hash file');
});
}else{
var oReq=new XMLHttpRequest();
oReq.open('GET', './zelda-botw.hashes.csv', true);
oReq.responseType='text';
oReq.onload=function(oEvent){
if(this.status===200) {
parseHashFile(responseText);
}else{
alert('Unexpected error: can\'t download hash file');
}
};
oReq.onerror=function(oEvent){
alert('Unexpected error: can\'t download hash file');
};
oReq.send(null);
}
},
filterHashes:function(regexFilter){
var findHashesIn;
empty('table');
this.filteredHashes=[];
if(regexFilter){
findHashesIn={};
for(var hash in HASHES){
if(regexFilter.test(HASHES[hash][1])){
findHashesIn[hash]=true;
}
}
}else{
findHashesIn=HASHES;
}
var previousHashValue=0;
for(var i=0x0c; i<tempFile.fileSize-4; i+=8){
var hashValue=tempFile.readU32(i);
if(hashValue===previousHashValue)
continue;
previousHashValue=hashValue;
if(findHashesIn[hashValue]){
this.filteredHashes.push({
type:HASHES[hashValue][0],
id:HASHES[hashValue][1],
offset:i
});
}else if(regexFilter===-1){
this.filteredHashes.push({
id:'* '+this._toHexInt(hashValue)
});
}
}
this.filteredHashes.sort(function(a,b){
if(a.id<b.id)return -1;
if(a.id>b.id)return 1;
return 0;
});
this.currentPage=0;
this.nPages=parseInt(this.filteredHashes.length/HASHES_PER_PAGE);
if(this.filteredHashes.length%HASHES_PER_PAGE!==0){
this.nPages++;
}
empty('select-page');
for(var i=0; i<this.nPages; i++){
var option=document.createElement('option');
option.innerHTML=i+1;
document.getElementById('select-page').appendChild(option);
}
this.setPage(0);
return this.filteredHashes;
},
setPage:function(newPage){
if(newPage>=0 && newPage<this.nPages){
document.getElementById('select-page').selectedIndex=newPage;
this.currentPage=newPage;
var filteredHashes=this.filteredHashes.slice(this.currentPage*HASHES_PER_PAGE, HASHES_PER_PAGE+this.currentPage*HASHES_PER_PAGE);
empty('table');
var container=document.createElement('tbody');
for(var i=0; i<filteredHashes.length; i++){
var hash=filteredHashes[i];
if(hash.type){
createHashInput(container, hash.id, hash.type, hash.offset)
}else{
addEditorRow(container, hash.id);
}
}
get('table').appendChild(container);
}
},
prevPage:function(){this.setPage(this.currentPage-1);},
nextPage:function(){this.setPage(this.currentPage+1);},
refreshResults:function(){
var filter=getValue('filters').trim();
var customFilter=getValue('custom-filter').trim();
if(filter){
this.filterHashes(new RegExp(filter));
}else if(customFilter){
this.filterHashes(new RegExp(customFilter, 'i'));
}else{
this.filterHashes(null);
}
}
}
}());