prevent flickering & .prettier
This commit is contained in:
parent
a1dd024714
commit
c2cf83bcb3
17 changed files with 293 additions and 265 deletions
7
.prettierrc
Normal file
7
.prettierrc
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"useTabs": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "all"
|
||||
}
|
|
@ -1,33 +1,28 @@
|
|||
<template>
|
||||
<div :class="
|
||||
disabled
|
||||
? 'button-wrapper disabled'
|
||||
: 'button-wrapper'
|
||||
">
|
||||
<div :class="disabled ? 'button-wrapper disabled' : 'button-wrapper'">
|
||||
<button @click="onClick" :disabled="disabled">{{ label }}</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CodeFormatter from "./scripts/codeFormatter";
|
||||
import CodeFormatter from './scripts/codeFormatter';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
disabled: { type: Boolean },
|
||||
onClick: { type: Function },
|
||||
label: { type: String }
|
||||
}
|
||||
label: { type: String },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.button-wrapper {
|
||||
position: relative;
|
||||
display: block;
|
||||
display: inline-block;
|
||||
max-width: 400px;
|
||||
min-width: 180px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button-wrapper.disabled button {
|
||||
|
@ -51,6 +46,7 @@ button {
|
|||
color: white;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
|
|
|
@ -34,10 +34,10 @@ export default {
|
|||
methods: {
|
||||
toggle(code) {
|
||||
code.selected = !code.selected;
|
||||
this.onSelectionChanged(this.availableCodes.filter((c) => c.selected));
|
||||
this.onSelectionChanged(this.availableCodes.filter(c => c.selected));
|
||||
},
|
||||
populate() {
|
||||
this.availableCodes = this.codes.map((c) => ({ ...c, selected: false }));
|
||||
this.availableCodes = this.codes.map(c => ({ ...c, selected: false }));
|
||||
},
|
||||
inspect(code) {
|
||||
this.onInspect(code);
|
||||
|
@ -64,10 +64,11 @@ ul li {
|
|||
display: block;
|
||||
min-width: 280px;
|
||||
padding-right: 15px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul li:nth-child(odd) {
|
||||
background: #e2e2e2;
|
||||
background: #e7e7e7;
|
||||
}
|
||||
|
||||
ul li:hover {
|
||||
|
@ -91,7 +92,7 @@ li {
|
|||
}
|
||||
|
||||
li::before {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
border-color: #a6a6a6;
|
||||
border-style: solid;
|
||||
|
@ -105,11 +106,17 @@ li::before {
|
|||
|
||||
li:hover::before {
|
||||
border-color: #fff;
|
||||
background-color: #ffc0cb;
|
||||
background-color: #1fa76e;
|
||||
}
|
||||
|
||||
li.checked::before {
|
||||
border-color: #fff;
|
||||
background-color: #d85e55;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 400px) {
|
||||
ul li {
|
||||
min-width: 180px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ButtonComponent from "./ButtonComponent";
|
||||
import CodeFormatter from "./scripts/codeFormatter";
|
||||
import ButtonComponent from './ButtonComponent';
|
||||
import CodeFormatter from './scripts/codeFormatter';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -26,22 +26,22 @@ export default {
|
|||
|
||||
if (this.stageLoaderCode)
|
||||
c.push({
|
||||
title: "Stage List Loader",
|
||||
author: "Noki Doki",
|
||||
date: "-",
|
||||
version: "",
|
||||
title: 'Stage List Loader',
|
||||
author: 'Noki Doki',
|
||||
date: '-',
|
||||
version: '',
|
||||
source: this.stageLoaderCode,
|
||||
});
|
||||
|
||||
console.log(`Preparing download for ${this.format}`);
|
||||
switch (this.format) {
|
||||
case "gct":
|
||||
case 'gct':
|
||||
CodeFormatter.generateGCT(c, this.versionIdentifier);
|
||||
break;
|
||||
case "dolphin":
|
||||
case 'dolphin':
|
||||
CodeFormatter.generateDolphinINI(c, this.versionIdentifier);
|
||||
break;
|
||||
case "gcm":
|
||||
case 'gcm':
|
||||
CodeFormatter.generateCheatManagerTXT(c, this.versionIdentifier);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
|
||||
<script>
|
||||
// Components
|
||||
import SelectComponent from "./SelectComponent";
|
||||
import SelectComponent from './SelectComponent';
|
||||
|
||||
// Data
|
||||
import downloadFormats from "../data/downloadFormats.json";
|
||||
import downloadFormats from '../data/downloadFormats.json';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -21,7 +21,7 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
options: downloadFormats.map((v) => ({
|
||||
options: downloadFormats.map(v => ({
|
||||
value: v.target,
|
||||
label: v.name,
|
||||
})),
|
||||
|
|
|
@ -1,22 +1,16 @@
|
|||
<template>
|
||||
<div>
|
||||
<div>
|
||||
<p v-if="isLoading">Loading...</p>
|
||||
</div>
|
||||
<section class="config">
|
||||
<div v-if="isLoading" class="loading-overlay">
|
||||
<div class="spinner"></div>
|
||||
</div>
|
||||
<div>
|
||||
<span>Game Version:</span>
|
||||
<VersionSelect
|
||||
:onChange="onVersionChanged"
|
||||
:selectedValue="selectedVersion"
|
||||
/>
|
||||
<VersionSelect :onChange="onVersionChanged" :selectedValue="selectedVersion" />
|
||||
</div>
|
||||
<div>
|
||||
<span>Download Format:</span>
|
||||
<FormatSelect
|
||||
:onChange="onFormatChanged"
|
||||
:selectedValue="selectedFormat"
|
||||
/>
|
||||
<FormatSelect :onChange="onFormatChanged" :selectedValue="selectedFormat" />
|
||||
</div>
|
||||
<div>
|
||||
<span>Use Stage Loader:</span>
|
||||
|
@ -47,15 +41,9 @@
|
|||
:onInspect="inspect"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="prevent-shrink"
|
||||
v-if="codes && codes.length > 0 && useStageLoader"
|
||||
>
|
||||
<div class="prevent-shrink" v-if="codes && codes.length > 0 && useStageLoader">
|
||||
<h3>Stage Loader</h3>
|
||||
<StageLoader
|
||||
:fastCodes="stageLoaderCodes"
|
||||
:onChange="onStageLoaderCodeChanged"
|
||||
/>
|
||||
<StageLoader :fastCodes="stageLoaderCodes" :onChange="onStageLoaderCodeChanged" />
|
||||
</div>
|
||||
|
||||
<div v-if="codes && codes.length > 0" class="help">
|
||||
|
@ -67,42 +55,31 @@
|
|||
<h3>Super Mario Sunshine Cheatfile Generator</h3>
|
||||
<div>
|
||||
<p>
|
||||
This is a cheatfile generator for Super Mario Sunshine speedrun
|
||||
practice. If this is your first time using the generator we highly
|
||||
recommend to check out the
|
||||
This is a cheatfile generator for Super Mario Sunshine speedrun practice. If this is
|
||||
your first time using the generator we highly recommend to check out the
|
||||
<a href="/guide.html" target="_blank">guide</a> first. Visit the
|
||||
<a href="/guide.html#troubleshooting" target="_blank"
|
||||
>the troubleshooting section</a
|
||||
>
|
||||
<a href="/guide.html#troubleshooting" target="_blank">the troubleshooting section</a>
|
||||
if you encounter any issues.
|
||||
</p>
|
||||
<div>
|
||||
<h4>The SMS Speedrunning Community</h4>
|
||||
<ul>
|
||||
<li>
|
||||
Discord:
|
||||
<a href="https://discord.gg/9dGJWEc" target="_blank"
|
||||
>https://discord.gg/9dGJWEc</a
|
||||
<a href="https://discord.gg/9dGJWEc" target="_blank" rel="noopener">Discord</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://speedrun.com/sms" target="_blank" rel="noopener"
|
||||
>Speedrun.com Leaderboards</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
Speedrun.com:
|
||||
<a href="https://speedrun.com/sms" target="_blank"
|
||||
>https://speedrun.com/sms</a
|
||||
<a href="https://twitter.com/SMSCommunity" target="_blank" rel="noopener"
|
||||
>Twitter: @SMSCommunity</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
Twitter:
|
||||
<a href="https://twitter.com/SMSCommunity" target="_blank"
|
||||
>https://twitter.com/SMSCommunity</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
Twitch:
|
||||
<a
|
||||
href="https://www.twitch.tv/SunshineCommunity"
|
||||
target="_blank"
|
||||
>https://www.twitch.tv/SunshineCommunity</a
|
||||
<a href="https://www.twitch.tv/SunshineCommunity" target="_blank" rel="noopener"
|
||||
>Twitch: SunshineCommunity</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -110,16 +87,14 @@
|
|||
<div>
|
||||
<p>
|
||||
GCT Generator © 2017 - {{ new Date().getFullYear() }}
|
||||
<a href="https://twitter.com/psychonauter" target="_blank"
|
||||
<a href="https://twitter.com/psychonauter" target="_blank" rel="noopener"
|
||||
>Psychonauter</a
|
||||
>,
|
||||
<a href="https://twitter.com/Qbe_Root" target="_blank"
|
||||
>Noki Doki</a
|
||||
>
|
||||
<a href="https://twitter.com/Qbe_Root" target="_blank" rel="noopener">Noki Doki</a>
|
||||
and
|
||||
<a href="https://twitter.com/srlMilk" target="_blank">Milk</a>.
|
||||
The source code is available on
|
||||
<a href="https://github.com/BitPatty/gctGenerator" target="_blank"
|
||||
<a href="https://twitter.com/srlMilk" target="_blank" rel="noopener">Milk</a>. The
|
||||
source code is available on
|
||||
<a href="https://github.com/BitPatty/gctGenerator" target="_blank" rel="noopener"
|
||||
>Github</a
|
||||
>.
|
||||
</p>
|
||||
|
@ -132,38 +107,38 @@
|
|||
|
||||
<script>
|
||||
// Components
|
||||
import VersionSelect from "./VersionSelect";
|
||||
import FormatSelect from "./FormatSelect";
|
||||
import SelectComponent from "./SelectComponent";
|
||||
import StageLoader from "./StageLoader";
|
||||
import CodeInfo from "./CodeInfo";
|
||||
import CodeList from "./CodeList";
|
||||
import DownloadButton from "./DownloadButton";
|
||||
import VersionSelect from './VersionSelect';
|
||||
import FormatSelect from './FormatSelect';
|
||||
import SelectComponent from './SelectComponent';
|
||||
import StageLoader from './StageLoader';
|
||||
import CodeInfo from './CodeInfo';
|
||||
import CodeList from './CodeList';
|
||||
import DownloadButton from './DownloadButton';
|
||||
|
||||
// Data
|
||||
import gameVersions from "../data/gameVersions.json";
|
||||
import gameVersions from '../data/gameVersions.json';
|
||||
|
||||
// Util
|
||||
import parseXml from "./scripts/parseXml";
|
||||
import parseXml from './scripts/parseXml';
|
||||
|
||||
// Libs
|
||||
import axios from "axios";
|
||||
import axios from 'axios';
|
||||
|
||||
export default {
|
||||
mounted() {
|
||||
Promise.all(
|
||||
gameVersions.map(async (v) => ({
|
||||
gameVersions.map(async v => ({
|
||||
identifier: v.identifier,
|
||||
cheats: parseXml((await axios.get(`/codes/${v.identifier}.xml`)).data),
|
||||
fastCodes: (await axios.get(`/codes/fast/${v.identifier}.json`)).data,
|
||||
}))
|
||||
})),
|
||||
)
|
||||
.then((codes) => {
|
||||
localStorage.setItem("codes", JSON.stringify(codes));
|
||||
.then(codes => {
|
||||
localStorage.setItem('codes', JSON.stringify(codes));
|
||||
this.isLoading = false;
|
||||
})
|
||||
.catch((err) => {
|
||||
if (localStorage.getItem("codes") != null) this.isLoading = false;
|
||||
.catch(err => {
|
||||
if (localStorage.getItem('codes') != null) this.isLoading = false;
|
||||
});
|
||||
},
|
||||
data() {
|
||||
|
@ -174,12 +149,12 @@ export default {
|
|||
selectedStageLoader: null,
|
||||
inspectingCode: null,
|
||||
selectedVersion: null,
|
||||
selectedFormat: "gct",
|
||||
selectedFormat: 'gct',
|
||||
useStageLoader: false,
|
||||
stageLoaderCodes: [],
|
||||
useStageLoaderOptions: [
|
||||
{ value: false, label: "No" },
|
||||
{ value: true, label: "Yes" },
|
||||
{ value: false, label: 'No' },
|
||||
{ value: true, label: 'Yes' },
|
||||
],
|
||||
};
|
||||
},
|
||||
|
@ -187,18 +162,16 @@ export default {
|
|||
onVersionChanged(e) {
|
||||
this.selectedVersion = e;
|
||||
this.selectedCheats = [];
|
||||
const storedCodes = JSON.parse(localStorage.getItem("codes"));
|
||||
this.codes = storedCodes.find((c) => c.identifier === e).cheats;
|
||||
this.stageLoaderCodes = storedCodes.find(
|
||||
(c) => c.identifier === e
|
||||
).fastCodes;
|
||||
const storedCodes = JSON.parse(localStorage.getItem('codes'));
|
||||
this.codes = storedCodes.find(c => c.identifier === e).cheats;
|
||||
this.stageLoaderCodes = storedCodes.find(c => c.identifier === e).fastCodes;
|
||||
this.inspectingCode = null;
|
||||
},
|
||||
onFormatChanged(e) {
|
||||
this.selectedFormat = e;
|
||||
},
|
||||
onStageLoaderChanged(e) {
|
||||
this.useStageLoader = e === true || e === "true";
|
||||
this.useStageLoader = e === true || e === 'true';
|
||||
if (!this.useStageLoader) this.selectedStageLoader = null;
|
||||
},
|
||||
onCheatSelectionChanged(e) {
|
||||
|
@ -232,11 +205,77 @@ section > div:not(:first-child) {
|
|||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.config {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.config .loading-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 999;
|
||||
text-align: center;
|
||||
background: #ffffff44;
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.config span {
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
.help {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.spinner:after {
|
||||
content: ' ';
|
||||
display: block;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
border: 6px solid #fff;
|
||||
border-color: #2eb9e2 transparent #2eb9e2 transparent;
|
||||
animation: spinner 1.2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
|
||||
.config .loading-overlay {
|
||||
-webkit-backdrop-filter: blur(1px);
|
||||
backdrop-filter: blur(1px);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1100px) {
|
||||
section {
|
||||
flex-wrap: wrap;
|
||||
display: block;
|
||||
margin-left: 0px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
section > div,
|
||||
section > div:not(:first-child) {
|
||||
margin-left: 0px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
<template>
|
||||
<div class="select-wrapper">
|
||||
<select @change="onValueChanged" autocomplete="off">
|
||||
<option v-if="placeholder != null" value="placeholder" selected disabled>
|
||||
{{ placeholder }}
|
||||
</option>
|
||||
<option v-if="placeholder != null" value="placeholder" selected disabled>{{ placeholder }}</option>
|
||||
<optgroup v-for="optGroup in optGroups" :label="optGroup.label">
|
||||
<option
|
||||
v-for="option in optGroup.options"
|
||||
:value="option.value"
|
||||
:selected="selectedValue && option.value === selectedValue"
|
||||
>{{ option.label }}</option
|
||||
>
|
||||
>{{ option.label }}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
@ -22,19 +19,19 @@ export default {
|
|||
selectedValue: { type: String },
|
||||
placeholder: { type: String },
|
||||
optGroups: { type: Array },
|
||||
onChange: { type: Function },
|
||||
onChange: { type: Function }
|
||||
},
|
||||
computed: {},
|
||||
data() {
|
||||
return {
|
||||
generation: 2,
|
||||
generation: 2
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onValueChanged(e) {
|
||||
this.onChange(e.target.value);
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -72,6 +69,10 @@ select {
|
|||
user-select: none;
|
||||
}
|
||||
|
||||
select::-ms-expand {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.select-wrapper:hover {
|
||||
background-color: #47c38b;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
<template>
|
||||
<div class="select-wrapper">
|
||||
<select @change="(e) => this.onChange(e.target.value)" autocomplete="off">
|
||||
<option v-if="placeholder != null" selected disabled>{{
|
||||
<option v-if="placeholder != null" selected disabled>
|
||||
{{
|
||||
placeholder
|
||||
}}</option>
|
||||
}}
|
||||
</option>
|
||||
<option
|
||||
v-for="option in options"
|
||||
:value="option.value"
|
||||
:selected="selectedValue && option.value === selectedValue"
|
||||
>{{ option.label }}</option
|
||||
>
|
||||
>{{ option.label }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -20,11 +21,11 @@ export default {
|
|||
selectedValue: { type: String },
|
||||
placeholder: { type: String },
|
||||
options: { type: Array },
|
||||
onChange: { type: Function },
|
||||
onChange: { type: Function }
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -62,6 +63,10 @@ select {
|
|||
user-select: none;
|
||||
}
|
||||
|
||||
select::-ms-expand {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.select-wrapper:hover {
|
||||
background-color: #47c38b;
|
||||
}
|
||||
|
|
|
@ -35,25 +35,17 @@
|
|||
<div class="config">
|
||||
<span>Route:</span>
|
||||
<ul class="level-select">
|
||||
<draggable
|
||||
v-model="selectedRoute"
|
||||
handle=".route-drag"
|
||||
ghost-class="ghost"
|
||||
>
|
||||
<draggable v-model="selectedRoute" handle=".route-drag" ghost-class="ghost">
|
||||
<li v-for="(level, index) in selectedRoute">
|
||||
<div class="route-drag">≡</div>
|
||||
|
||||
<GroupSelectComponent
|
||||
:selectedValue="level.value"
|
||||
:optGroups="stageLoaderLevelOptions"
|
||||
:onChange="(e) => onStageLoaderLevelChanged(index, e)"
|
||||
:onChange="e => onStageLoaderLevelChanged(index, e)"
|
||||
:key="index"
|
||||
/>
|
||||
<button
|
||||
@click="onLevelDeleted(index)"
|
||||
type="button"
|
||||
class="route-remove"
|
||||
>
|
||||
<button @click="onLevelDeleted(index)" type="button" class="route-remove">
|
||||
×
|
||||
</button>
|
||||
</li>
|
||||
|
@ -88,19 +80,19 @@
|
|||
|
||||
<script>
|
||||
// Components
|
||||
import SelectComponent from "./SelectComponent";
|
||||
import ButtonComponent from "./ButtonComponent";
|
||||
import GroupSelectComponent from "./GroupSelectComponent";
|
||||
import SelectComponent from './SelectComponent';
|
||||
import ButtonComponent from './ButtonComponent';
|
||||
import GroupSelectComponent from './GroupSelectComponent';
|
||||
|
||||
// Data
|
||||
import stageLoaderLevels from "../data/stageLoaderLevels.json";
|
||||
import stageLoaderPresets from "../data/stageLoaderPresets.json";
|
||||
import stageLoaderLevels from '../data/stageLoaderLevels.json';
|
||||
import stageLoaderPresets from '../data/stageLoaderPresets.json';
|
||||
|
||||
// Util
|
||||
import generateStageLoaderCode from "./scripts/generateStageLoadercode";
|
||||
import generateStageLoaderCode from './scripts/generateStageLoadercode';
|
||||
|
||||
// Lib
|
||||
import draggable from "vuedraggable";
|
||||
import draggable from 'vuedraggable';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -116,30 +108,30 @@ export default {
|
|||
stageLoaderLevelOptions: stageLoaderLevels,
|
||||
stageLoaderPresetOptions: stageLoaderPresets,
|
||||
removeDialogueOptions: [
|
||||
{ value: "yes", label: "Always" },
|
||||
{ value: "pv5", label: "Not in Pinna 5" },
|
||||
{ value: "no", label: "Don't include" },
|
||||
{ value: 'yes', label: 'Always' },
|
||||
{ value: 'pv5', label: 'Not in Pinna 5' },
|
||||
{ value: 'no', label: "Don't include" },
|
||||
],
|
||||
skippableFMVsOptions: [
|
||||
{ value: "yes", label: "Always" },
|
||||
{ value: "pp", label: "Not in Pinna" },
|
||||
{ value: "no", label: "Don't include" },
|
||||
{ value: 'yes', label: 'Always' },
|
||||
{ value: 'pp', label: 'Not in Pinna' },
|
||||
{ value: 'no', label: "Don't include" },
|
||||
],
|
||||
levelOrderOptions: [
|
||||
{ value: "list", label: "As specified" },
|
||||
{ value: "shuffle", label: "Random, no duplicates" },
|
||||
{ value: "random", label: "Fully random" },
|
||||
{ value: 'list', label: 'As specified' },
|
||||
{ value: 'shuffle', label: 'Random, no duplicates' },
|
||||
{ value: 'random', label: 'Fully random' },
|
||||
],
|
||||
postGameOptions: [
|
||||
{ value: "0F00", label: "Return to title screen" },
|
||||
{ value: "0109", label: "Load the flooded plaza" },
|
||||
{ value: "3400", label: "Load post-Corona plaza" },
|
||||
{ value: "3C00", label: "Load the Bowser fight" },
|
||||
{ value: '0F00', label: 'Return to title screen' },
|
||||
{ value: '0109', label: 'Load the flooded plaza' },
|
||||
{ value: '3400', label: 'Load post-Corona plaza' },
|
||||
{ value: '3C00', label: 'Load the Bowser fight' },
|
||||
],
|
||||
removeDialogSelection: "yes",
|
||||
skippableFMVsSelection: "yes",
|
||||
levelOrderSelection: "list",
|
||||
postGameSelection: "0F00",
|
||||
removeDialogSelection: 'yes',
|
||||
skippableFMVsSelection: 'yes',
|
||||
levelOrderSelection: 'list',
|
||||
postGameSelection: '0F00',
|
||||
generation: 0,
|
||||
};
|
||||
},
|
||||
|
@ -182,18 +174,17 @@ export default {
|
|||
|
||||
if (
|
||||
this.selectedRoute?.length > 0 &&
|
||||
!confirm("Loading a preset will erase your current list. Continue?")
|
||||
!confirm('Loading a preset will erase your current list. Continue?')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const preset = e.split(";")[0];
|
||||
const ending = e.split(";")[1];
|
||||
const preset = e.split(';')[0];
|
||||
const ending = e.split(';')[1];
|
||||
|
||||
const newRoute = [];
|
||||
|
||||
for (let i = 0; i <= preset.length - 4; i += 4)
|
||||
newRoute.push({ value: preset.substr(i, 4) });
|
||||
for (let i = 0; i <= preset.length - 4; i += 4) newRoute.push({ value: preset.substr(i, 4) });
|
||||
|
||||
this.selectedRoute = newRoute;
|
||||
|
||||
|
@ -201,10 +192,7 @@ export default {
|
|||
this.updateCode();
|
||||
},
|
||||
onClearList() {
|
||||
if (
|
||||
this.selectedRoute?.length > 0 &&
|
||||
!confirm("Do you really want to clear the list?")
|
||||
)
|
||||
if (this.selectedRoute?.length > 0 && !confirm('Do you really want to clear the list?'))
|
||||
return;
|
||||
|
||||
this.selectedRoute = [];
|
||||
|
@ -222,16 +210,16 @@ export default {
|
|||
return;
|
||||
}
|
||||
|
||||
console.log("Generating new Stageloader-Code");
|
||||
console.log('Generating new Stageloader-Code');
|
||||
this.onChange(
|
||||
generateStageLoaderCode(
|
||||
this.fastCodes,
|
||||
this.selectedRoute.map((v) => v.value),
|
||||
this.selectedRoute.map(v => v.value),
|
||||
this.levelOrderSelection,
|
||||
this.postGameSelection,
|
||||
this.skippableFMVsSelection,
|
||||
this.removeDialogSelection
|
||||
)
|
||||
this.removeDialogSelection,
|
||||
),
|
||||
);
|
||||
},
|
||||
},
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import SelectComponent from "./SelectComponent";
|
||||
import SelectComponent from './SelectComponent';
|
||||
|
||||
import gameVersions from "../data/gameVersions.json";
|
||||
import gameVersions from '../data/gameVersions.json';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -19,7 +19,7 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
options: gameVersions.map((v) => ({
|
||||
options: gameVersions.map(v => ({
|
||||
value: v.identifier,
|
||||
label: v.name,
|
||||
})),
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
export default class CodeFormatter {
|
||||
static generateGCT(codes, version) {
|
||||
let code = "00D0C0DE00D0C0DE";
|
||||
codes.forEach((c) => (code += c.source));
|
||||
code += "FF00000000000000";
|
||||
let code = '00D0C0DE00D0C0DE';
|
||||
codes.forEach(c => (code += c.source));
|
||||
code += 'FF00000000000000';
|
||||
|
||||
let rawData = new Uint8Array(code.length / 2);
|
||||
|
||||
|
@ -14,14 +14,14 @@ export default class CodeFormatter {
|
|||
}
|
||||
|
||||
static generateDolphinINI(codes, version) {
|
||||
let data = "Paste the following on top of your games .ini file:\r\n[Gecko]";
|
||||
let data = 'Paste the following on top of your games .ini file:\r\n[Gecko]';
|
||||
|
||||
codes.forEach((code) => {
|
||||
codes.forEach(code => {
|
||||
data += `\r\n$${code.title} (${code.author}) [${code.date}]\r\n`;
|
||||
data += code.source
|
||||
.match(/.{8}/g)
|
||||
.join(" ")
|
||||
.replace(/(.{17})./g, "$1\r\n");
|
||||
.join(' ')
|
||||
.replace(/(.{17})./g, '$1\r\n');
|
||||
});
|
||||
|
||||
this.downloadFile(data, `${version}.txt`);
|
||||
|
@ -30,12 +30,12 @@ export default class CodeFormatter {
|
|||
static generateCheatManagerTXT(codes, version) {
|
||||
let data = `${version}\r\nSuper Mario Sunshine`;
|
||||
|
||||
codes.forEach((code) => {
|
||||
codes.forEach(code => {
|
||||
data += `\r\n\r\n${code.title} (${code.author}) [${code.date}]\r\n`;
|
||||
data += code.source
|
||||
.match(/.{8}/g)
|
||||
.join(" ")
|
||||
.replace(/(.{17})./g, "$1\r\n");
|
||||
.join(' ')
|
||||
.replace(/(.{17})./g, '$1\r\n');
|
||||
});
|
||||
|
||||
this.downloadFile(data, `${version}.txt`);
|
||||
|
@ -43,13 +43,12 @@ export default class CodeFormatter {
|
|||
|
||||
static downloadFile(data, filename) {
|
||||
var file = new Blob([data], {
|
||||
type: "application/octet-stream",
|
||||
type: 'application/octet-stream',
|
||||
});
|
||||
|
||||
if (window.navigator.msSaveOrOpenBlob)
|
||||
window.navigator.msSaveOrOpenBlob(file, filename);
|
||||
if (window.navigator.msSaveOrOpenBlob) window.navigator.msSaveOrOpenBlob(file, filename);
|
||||
else {
|
||||
var a = document.createElement("a"),
|
||||
var a = document.createElement('a'),
|
||||
url = window.URL.createObjectURL(file);
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
|
|
|
@ -4,7 +4,7 @@ const generateStageLoaderCode = (
|
|||
routeOrder,
|
||||
routeEnding,
|
||||
fmvSkips,
|
||||
dialgueSkips
|
||||
dialgueSkips,
|
||||
) => {
|
||||
const loadStageLength = {
|
||||
list: 0x20,
|
||||
|
@ -12,110 +12,101 @@ const generateStageLoaderCode = (
|
|||
shuffle: 0x40,
|
||||
}[routeOrder];
|
||||
|
||||
let codes = "";
|
||||
let codes = '';
|
||||
|
||||
// Reset counter on file select
|
||||
codes +=
|
||||
"0" +
|
||||
'0' +
|
||||
(0x04000000 + (gameConfig.fileSelect & 0x01ffffff)).toString(16) +
|
||||
(
|
||||
0x48000001 +
|
||||
((gameConfig.system + 0x52c - gameConfig.fileSelect) & 0x03fffffc)
|
||||
).toString(16);
|
||||
(0x48000001 + ((gameConfig.system + 0x52c - gameConfig.fileSelect) & 0x03fffffc)).toString(16);
|
||||
|
||||
// Load next stage on Shine get
|
||||
codes +=
|
||||
"0" +
|
||||
'0' +
|
||||
(0x04000000 + (gameConfig.shineGet & 0x01ffffff)).toString(16) +
|
||||
(
|
||||
0x48000001 +
|
||||
((gameConfig.system + 0x53c - gameConfig.shineGet) & 0x03fffffc)
|
||||
).toString(16);
|
||||
(0x48000001 + ((gameConfig.system + 0x53c - gameConfig.shineGet) & 0x03fffffc)).toString(16);
|
||||
|
||||
// Reload stage on exit area
|
||||
codes +=
|
||||
"0" +
|
||||
(0x04000000 + (gameConfig.system & 0x01ffffff)).toString(16) +
|
||||
"48000511";
|
||||
codes += '0' + (0x04000000 + (gameConfig.system & 0x01ffffff)).toString(16) + '48000511';
|
||||
|
||||
// Set next stage on game over
|
||||
codes +=
|
||||
"0" +
|
||||
'0' +
|
||||
(0x06000000 + ((gameConfig.system + 0xb4) & 0x01ffffff)).toString(16) +
|
||||
"000000084800048948000044";
|
||||
'000000084800048948000044';
|
||||
|
||||
// Reset timer on secret death
|
||||
codes +=
|
||||
(0xc2000000 + ((gameConfig.system + 0x208) & 0x01ffffff)).toString(16) +
|
||||
"000000033C60817F38000001980300FF881C00006000000000000000";
|
||||
'000000033C60817F38000001980300FF881C00006000000000000000';
|
||||
|
||||
// Reset coin count on loading main world
|
||||
codes +=
|
||||
(0xc2000000 + ((gameConfig.shineGet - 0x674) & 0x01ffffff)).toString(16) +
|
||||
"00000005887D00002C030002418000142C0300074182000C2C03000A418000087C0400406000000000000000";
|
||||
'00000005887D00002C030002418000142C0300074182000C2C03000A418000087C0400406000000000000000';
|
||||
|
||||
// Overwrite decideNextStage(void) with useful routines
|
||||
codes +=
|
||||
"0" +
|
||||
'0' +
|
||||
(0x06000000 + ((gameConfig.system + 0x510) & 0x01ffffff)).toString(16) +
|
||||
("0000000" + (loadStageLength + 0x5c).toString(16)).slice(-8) +
|
||||
"3C60817F38000001980300FFA00300023C60" +
|
||||
('0000000' + (loadStageLength + 0x5c).toString(16)).slice(-8) +
|
||||
'3C60817F38000001980300FFA00300023C60' +
|
||||
gameConfig.gpAppHi +
|
||||
"B003" +
|
||||
'B003' +
|
||||
gameConfig.gpAppLo +
|
||||
"4E800020" + // reload current level
|
||||
"3C60817F" +
|
||||
'4E800020' + // reload current level
|
||||
'3C60817F' +
|
||||
(0x38800000 + ((selectedLevels.length * 2) & 0x0000ffff)).toString(16) +
|
||||
"B08300004E800020" + // reset counter
|
||||
"3C60817F38000001980300FFA00300002C00000038E0" +
|
||||
'B08300004E800020' + // reset counter
|
||||
'3C60817F38000001980300FFA00300002C00000038E0' +
|
||||
routeEnding + // load next stage - the fun begins
|
||||
(0x40810000 + (loadStageLength & 0x0000fffc)).toString(16) +
|
||||
"7C8802A6600000007CC802A67C8803A6";
|
||||
'7C8802A6600000007CC802A67C8803A6';
|
||||
|
||||
switch (routeOrder) {
|
||||
case "list":
|
||||
codes += "3400FFFEB00300007CE6022E";
|
||||
case 'list':
|
||||
codes += '3400FFFEB00300007CE6022E';
|
||||
break;
|
||||
case "random":
|
||||
codes += "7C8C42E67CA403967CA501D67C8520505484003C7CE6222E";
|
||||
case 'random':
|
||||
codes += '7C8C42E67CA403967CA501D67C8520505484003C7CE6222E';
|
||||
break;
|
||||
case "shuffle":
|
||||
case 'shuffle':
|
||||
codes +=
|
||||
"7C8C42E67CA403967CA501D67C8520505484003C3400FFFEB00300007CE6222E7CA6022E7CA6232E7CE6032E";
|
||||
'7C8C42E67CA403967CA501D67C8520505484003C3400FFFEB00300007CE6222E7CA6022E7CA6232E7CE6032E';
|
||||
}
|
||||
|
||||
codes +=
|
||||
"B0E300023C60" +
|
||||
'B0E300023C60' +
|
||||
gameConfig.gpAppHi +
|
||||
"B0E3" +
|
||||
'B0E3' +
|
||||
gameConfig.gpAppLo +
|
||||
"806D" +
|
||||
'806D' +
|
||||
gameConfig.fmOffset +
|
||||
"98E300DF4E800020" +
|
||||
(routeOrder === "random" ? "" : "00000000");
|
||||
'98E300DF4E800020' +
|
||||
(routeOrder === 'random' ? '' : '00000000');
|
||||
|
||||
selectedLevels.reverse();
|
||||
|
||||
while (selectedLevels.length % 4) selectedLevels.push("0000");
|
||||
while (selectedLevels.length % 4) selectedLevels.push('0000');
|
||||
|
||||
// Insert the list of levels into the loader
|
||||
codes +=
|
||||
(0xc2000000 + ((gameConfig.system + 0x55c) & 0x01ffffff)).toString(16) +
|
||||
("0000000" + (selectedLevels.length / 4 + 1).toString(16)).slice(-8) +
|
||||
('0000000' + (selectedLevels.length / 4 + 1).toString(16)).slice(-8) +
|
||||
(0x48000001 + ((selectedLevels.length * 2 + 4) & 0x03fffffc)).toString(16) +
|
||||
selectedLevels.join("") +
|
||||
"00000000";
|
||||
selectedLevels.join('') +
|
||||
'00000000';
|
||||
|
||||
// Load next stage on setNextStage into main level
|
||||
codes +=
|
||||
"0" +
|
||||
'0' +
|
||||
(0x06000000 + ((gameConfig.system + 0x118c) & 0x01ffffff)).toString(16) +
|
||||
"00000028B07D00143C80817F38000000B00400FFA0010038B01D00122C1C00094181000C4BFFF391B0E10038";
|
||||
'00000028B07D00143C80817F38000000B00400FFA0010038B01D00122C1C00094181000C4BFFF391B0E10038';
|
||||
|
||||
// Setup timer
|
||||
codes +=
|
||||
(0xc2000000 + (gameConfig.proc & 0x01ffffff)).toString(16) +
|
||||
"000000053CA0817F388000009085010C880500FF98050100988500FF38800001988501016000000000000000";
|
||||
'000000053CA0817F388000009085010C880500FF98050100988500FF38800001988501016000000000000000';
|
||||
|
||||
codes = codes.toUpperCase();
|
||||
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
const parseXml = (xmlString) => {
|
||||
const parseXml = xmlString => {
|
||||
const codeCollection = new DOMParser()
|
||||
.parseFromString(xmlString, "text/xml")
|
||||
.getElementsByTagName("code");
|
||||
.parseFromString(xmlString, 'text/xml')
|
||||
.getElementsByTagName('code');
|
||||
|
||||
const codes = [...codeCollection];
|
||||
|
||||
return codes.map((code) => ({
|
||||
author: parseTextNode(code, "author"),
|
||||
title: parseTextNode(code, "title"),
|
||||
description: parseTextNode(code, "description"),
|
||||
version: parseTextNode(code, "version"),
|
||||
date: parseTextNode(code, "date"),
|
||||
source: parseTextNode(code, "source").replace(/[\s\n\r\t]+/gm, ""),
|
||||
return codes.map(code => ({
|
||||
author: parseTextNode(code, 'author'),
|
||||
title: parseTextNode(code, 'title'),
|
||||
description: parseTextNode(code, 'description'),
|
||||
version: parseTextNode(code, 'version'),
|
||||
date: parseTextNode(code, 'date'),
|
||||
source: parseTextNode(code, 'source').replace(/[\s\n\r\t]+/gm, ''),
|
||||
}));
|
||||
};
|
||||
|
||||
const parseTextNode = (node, identifier) =>
|
||||
node.getElementsByTagName(identifier)[0].textContent;
|
||||
const parseTextNode = (node, identifier) => node.getElementsByTagName(identifier)[0].textContent;
|
||||
|
||||
export default parseXml;
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
const { description } = require("../../package");
|
||||
const { description } = require('../../package');
|
||||
|
||||
module.exports = {
|
||||
title: "GCT Generator",
|
||||
title: 'GCT Generator',
|
||||
description: description,
|
||||
head: [
|
||||
["meta", { name: "theme-color", content: "#3eaf7c" }],
|
||||
["meta", { name: "apple-mobile-web-app-capable", content: "yes" }],
|
||||
[
|
||||
"meta",
|
||||
{ name: "apple-mobile-web-app-status-bar-style", content: "black" },
|
||||
],
|
||||
['meta', { name: 'theme-color', content: '#3eaf7c' }],
|
||||
['meta', { name: 'viewport', content: 'width=device-width, initial-scale=1' }],
|
||||
],
|
||||
|
||||
/**
|
||||
|
@ -18,27 +14,27 @@ module.exports = {
|
|||
* ref:https://v1.vuepress.vuejs.org/theme/default-theme-config.html
|
||||
*/
|
||||
themeConfig: {
|
||||
repo: "BitPatty/gctGenerator",
|
||||
repo: 'BitPatty/gctGenerator',
|
||||
editLinks: true,
|
||||
docsDir: "docs",
|
||||
editLinkText: "Edit this page on GitHub",
|
||||
docsDir: 'docs',
|
||||
editLinkText: 'Edit this page on GitHub',
|
||||
lastUpdated: false,
|
||||
nav: [
|
||||
{
|
||||
text: "Cookbook",
|
||||
link: "/guide.html",
|
||||
text: 'Cookbook',
|
||||
link: '/guide.html',
|
||||
},
|
||||
{
|
||||
text: "Changelog",
|
||||
link: "/changelog.html",
|
||||
text: 'Changelog',
|
||||
link: '/changelog.html',
|
||||
},
|
||||
{
|
||||
text: "Installing IOS58",
|
||||
link: "/ios58.html",
|
||||
text: 'Installing IOS58',
|
||||
link: '/ios58.html',
|
||||
},
|
||||
{
|
||||
text: "Sunshine Discord",
|
||||
link: "https://discord.gg/9dGJWEc",
|
||||
text: 'Sunshine Discord',
|
||||
link: 'https://discord.gg/9dGJWEc',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -46,5 +42,5 @@ module.exports = {
|
|||
/**
|
||||
* Apply plugins,ref:https://v1.vuepress.vuejs.org/zh/plugin/
|
||||
*/
|
||||
plugins: ["@vuepress/plugin-back-to-top", "@vuepress/plugin-medium-zoom"],
|
||||
plugins: ['@vuepress/plugin-back-to-top', '@vuepress/plugin-medium-zoom'],
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@ export default ({
|
|||
Vue, // the version of Vue being used in the VuePress app
|
||||
options, // the options for the root Vue instance
|
||||
router, // the router instance for the app
|
||||
siteData // site metadata
|
||||
siteData, // site metadata
|
||||
}) => {
|
||||
// ...apply enhancements for the site.
|
||||
}
|
||||
};
|
||||
|
|
Before Width: | Height: | Size: 318 B After Width: | Height: | Size: 318 B |
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "gctGenerator",
|
||||
"version": "0.0.1",
|
||||
"name": "gctgenerator",
|
||||
"version": "3.0.1",
|
||||
"description": "Super Mario Sunshine Practice File Generator",
|
||||
"main": "index.js",
|
||||
"authors": {
|
||||
|
|
Loading…
Reference in a new issue