Multiworld stuff
This commit is contained in:
93
src/components/Multi.vue
Normal file
93
src/components/Multi.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
import { Base64 } from "js-base64";
|
||||
import axios from "axios";
|
||||
|
||||
export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
multidata: null,
|
||||
worlds: {},
|
||||
error: null,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
id: "",
|
||||
},
|
||||
async mounted() {
|
||||
document.title = `ALttPR Multiworld: ${this.id}`;
|
||||
await this.fetchMulti();
|
||||
},
|
||||
computed: {
|
||||
permalink() {
|
||||
return `/multi/${this.id}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async fetchMulti() {
|
||||
await axios.get(`/multi/${this.id}`)
|
||||
.then(response => {
|
||||
if (response && response.data && response.data.multidata) {
|
||||
const multi = response.data;
|
||||
this.multidata = Base64.toUint8Array(multi.multidata);
|
||||
this.worlds = multi.worlds;
|
||||
} else {
|
||||
this.error = "Error loading multiworld.";
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.response?.status == 409) {
|
||||
// still generating, try again
|
||||
setTimeout(this.fetchMulti.bind(this), 10000);
|
||||
} else {
|
||||
this.error = "Multiworld not found. :(";
|
||||
}
|
||||
});
|
||||
},
|
||||
async downloadMultidata() {
|
||||
const blob = new Blob([this.multidata], { type: 'octet/stream' });
|
||||
const link = document.getElementById('downloader');
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = `GK_${this.id}_multidata`;
|
||||
link.click();
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mw-30">
|
||||
<div v-if="multidata" class="card content-div m-3">
|
||||
<div class="card-header">
|
||||
Permalink: <a :href="permalink">{{ permalink }}</a>
|
||||
</div>
|
||||
<ul class="list-group list-group-flush">
|
||||
<li v-for="world in worlds" class="list-group-item">
|
||||
{{ world.name }}: <a :href="`/seed/${world.id}`">/seed/{{ world.id }}</a>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<button type="submit" class="btn btn-primary submit-btn" :disabled="!multidata" @click="downloadMultidata">
|
||||
Download Multidata!
|
||||
</button>
|
||||
<a id="downloader" style="display: none;" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-else-if="error" class="error-message">
|
||||
{{ error }}
|
||||
</div>
|
||||
<div v-else>
|
||||
<img class="center" src="/bludormspinbig.gif" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.error-message {
|
||||
text-align: center;
|
||||
font-size: xx-large;
|
||||
font-weight: bold;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
</style>
|
||||
@@ -69,6 +69,9 @@ export default defineComponent({
|
||||
},
|
||||
settingsMatch(newSettings, preset) {
|
||||
for (const settingName of Object.keys(newSettings)) {
|
||||
if (settingName == "player_name") {
|
||||
continue;
|
||||
}
|
||||
if (preset[settingName] != newSettings[settingName]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ export default defineComponent({
|
||||
patch: null,
|
||||
error: null,
|
||||
settings: null,
|
||||
multi: null,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
@@ -63,6 +64,7 @@ export default defineComponent({
|
||||
dataLoaded(patch, seedData) {
|
||||
this.patch = patch;
|
||||
this.settings = seedData.settings;
|
||||
this.multi = seedData.parent;
|
||||
},
|
||||
async fetchSeed() {
|
||||
await axios.get(`/seed/${this.id}`)
|
||||
@@ -175,7 +177,7 @@ export default defineComponent({
|
||||
</li>
|
||||
<li v-if="settings" class="list-group-item">
|
||||
<div class="mb-1">
|
||||
<SeedSettings :settings="settings" />
|
||||
<SeedSettings :settings="settings" :multi="multi" />
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
|
||||
@@ -7,6 +7,7 @@ import mustache from "mustache";
|
||||
export default defineComponent({
|
||||
props: {
|
||||
settings: {},
|
||||
multi: null,
|
||||
},
|
||||
computed: {
|
||||
settingsDisplay() {
|
||||
@@ -29,7 +30,14 @@ export default defineComponent({
|
||||
|| (this.settings.maps && this.settings.maps != "dungeon")
|
||||
|| (this.settings.compasses && this.settings.compasses != "dungeon")
|
||||
|| (this.settings.prize_shuffle && this.settings.prize_shuffle != "vanilla");
|
||||
}
|
||||
},
|
||||
multilink() {
|
||||
if (this.multi) {
|
||||
return `/multi/${this.multi}`;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
@@ -37,6 +45,10 @@ export default defineComponent({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="multi">
|
||||
Part of Multiworld: <a :href="multilink">{{ multilink }}</a>
|
||||
<hr class="mt-2 mb-2" />
|
||||
</div>
|
||||
<div v-if="settings.randomizer && settingsDisplay.randomizer[settings.randomizer]">
|
||||
{{ settingsDisplay.randomizer[settings.randomizer] }}
|
||||
<hr class="mt-2 mb-2" />
|
||||
|
||||
@@ -19,6 +19,7 @@ export default defineComponent({
|
||||
name: null,
|
||||
color: "primary",
|
||||
generator: null,
|
||||
prefix: null,
|
||||
},
|
||||
watch: {
|
||||
async modelValue(newValue, oldValue) {
|
||||
@@ -44,7 +45,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
this.selected = await localforage.getItem(`setting_${this.name}`) ?? this.settings.default;
|
||||
this.selected = await localforage.getItem(`${this.prefix}setting_${this.name}`) ?? this.settings.default;
|
||||
this.change();
|
||||
},
|
||||
methods: {
|
||||
@@ -53,7 +54,7 @@ export default defineComponent({
|
||||
await this.updateLocalForage();
|
||||
},
|
||||
async updateLocalForage() {
|
||||
await localforage.setItem(`setting_${this.name}`, this.selected);
|
||||
await localforage.setItem(`${this.prefix}setting_${this.name}`, this.selected);
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -64,9 +65,9 @@ export default defineComponent({
|
||||
<div class="nav nav-pills nav-fill mt-1 mb-1">
|
||||
<template v-for="value of settings.order ?? Object.keys(settings.values)">
|
||||
<template v-if="settings.values[value]">
|
||||
<input type="radio" class="btn-check" :name="name" :id="`${name}_${value}`"
|
||||
<input type="radio" class="btn-check" :name="`${prefix}${name}`" :id="`${prefix}${name}_${value}`"
|
||||
autocomplete="off" :value="value" v-model="selected" @change="change" />
|
||||
<label :class="`btn btn-outline-${color} nav-item m-1`" :for="`${name}_${value}`">
|
||||
<label :class="`btn btn-outline-${color} nav-item m-1`" :for="`${prefix}${name}_${value}`">
|
||||
{{ settings.values[value].display }}
|
||||
</label>
|
||||
</template>
|
||||
|
||||
209
src/components/SettingsPage.vue
Normal file
209
src/components/SettingsPage.vue
Normal file
@@ -0,0 +1,209 @@
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
import axios from "axios";
|
||||
import { Modal } from "bootstrap";
|
||||
|
||||
import AccordionItem from "@/components/AccordionItem.vue";
|
||||
import PresetPicker from "@/components/PresetPicker.vue";
|
||||
import SettingPicker from "@/components/SettingPicker.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
AccordionItem,
|
||||
PresetPicker,
|
||||
SettingPicker,
|
||||
},
|
||||
emits: [
|
||||
'update:modelValue'
|
||||
],
|
||||
props: {
|
||||
modelValue: {},
|
||||
prefix: null,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
set: {},
|
||||
existingLocalPresets: [],
|
||||
newPresetName: "",
|
||||
replacePreset: null,
|
||||
modal: null,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.modal = new Modal(document.getElementById("savePresetModal"), {});
|
||||
},
|
||||
watch: {
|
||||
set: {
|
||||
handler(newValue, oldValue) {
|
||||
this.$refs.preset.settingChanged(newValue);
|
||||
this.$emit("update:modelValue", this.set);
|
||||
},
|
||||
deep: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async generate(race) {
|
||||
const settings = {
|
||||
randomizer: "base",
|
||||
race: race ? "race" : "normal"
|
||||
};
|
||||
for (const setting of Object.keys(this.set)) {
|
||||
settings[setting] = this.set[setting];
|
||||
}
|
||||
await axios.post("/generate", settings)
|
||||
.then(response => {
|
||||
const id = response.data;
|
||||
this.$router.push(`/seed/${id}`);
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
presetSelected(preset) {
|
||||
for (const setting of Object.keys(this.set)) {
|
||||
if (preset[setting] != undefined) {
|
||||
this.set[setting] = preset[setting];
|
||||
}
|
||||
}
|
||||
},
|
||||
savePreset(names) {
|
||||
this.newPresetName = "";
|
||||
this.existingLocalPresets = names;
|
||||
this.modal.show();
|
||||
},
|
||||
async modalSavePreset() {
|
||||
const preset = JSON.parse(JSON.stringify(this.set));
|
||||
preset.display = this.newPresetName;
|
||||
if (this.replacePreset != null) {
|
||||
preset.display = this.existingLocalPresets[this.replacePreset];
|
||||
}
|
||||
await this.$refs.preset.savePreset(this.replacePreset, preset);
|
||||
this.modal.hide();
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="modal" tabindex="-1" id="savePresetModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Save Preset</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="input-group mb-3">
|
||||
<select v-model="replacePreset" class="form-select">
|
||||
<option :value="null" selected>New</option>
|
||||
<optgroup v-if="existingLocalPresets.length" label="Overwrite Preset:">
|
||||
<template v-for="(preset, idx) of existingLocalPresets">
|
||||
<option :value="idx">
|
||||
{{ preset }}
|
||||
</option>
|
||||
</template>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-3" v-if="replacePreset == null">
|
||||
<label class="input-group-text" for="new-preset-name">
|
||||
Name
|
||||
</label>
|
||||
<input type="text" class="form-control" placeholder="Display Name"
|
||||
id="new-preset-name" v-model="newPresetName" autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
<button :disabled="replacePreset == null && newPresetName.length == 0" type="button"
|
||||
class="btn btn-primary" @click="modalSavePreset">
|
||||
Save Preset
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="settings" class="accordion accordion-flush">
|
||||
<AccordionItem>
|
||||
<PresetPicker ref="preset" generator="base" @selected="presetSelected"
|
||||
@save="savePreset" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="true">
|
||||
<template #header>
|
||||
<b>World:</b>
|
||||
</template>
|
||||
<SettingPicker color="primary" v-model="set.mode" name="mode" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="primary" v-model="set.weapons" name="weapons" generator="base" :prefix="prefix" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="true">
|
||||
<template #header>
|
||||
<b>Goal:</b>
|
||||
</template>
|
||||
<SettingPicker color="success" v-model="set.goal" name="goal" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="success" v-if="['ganon', 'fast_ganon'].includes(this.set.goal)"
|
||||
v-model="set.crystals_ganon" name="crystals_ganon" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="success" v-model="set.crystals_gt" name="crystals_gt" generator="base" :prefix="prefix" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="false">
|
||||
<template #header>
|
||||
<b>Entrance Shuffle:</b>
|
||||
</template>
|
||||
<SettingPicker color="warning" v-model="set.entrance_shuffle" name="entrance_shuffle" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="warning" v-if="this.set.entrance_shuffle != 'vanilla'"
|
||||
v-model="set.skull_woods" name="skull_woods" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="warning" v-if="this.set.entrance_shuffle != 'vanilla'"
|
||||
v-model="set.linked_drops" name="linked_drops" generator="base" :prefix="prefix" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="false">
|
||||
<template #header>
|
||||
<b>Dungeon Shuffle:</b>
|
||||
</template>
|
||||
<SettingPicker color="danger" v-model="set.door_shuffle" name="door_shuffle" generator="base" />
|
||||
<SettingPicker color="danger" v-if="this.set.door_shuffle != 'vanilla'"
|
||||
v-model="set.door_lobbies" name="door_lobbies" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="danger" v-if="this.set.door_shuffle != 'vanilla'"
|
||||
v-model="set.door_type_mode" name="door_type_mode" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="danger" v-if="this.set.door_shuffle != 'vanilla'"
|
||||
v-model="set.trap_door_mode" name="trap_door_mode" generator="base" :prefix="prefix" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="false">
|
||||
<template #header>
|
||||
<b>Enemizer:</b>
|
||||
</template>
|
||||
<SettingPicker color="success" v-model="set.boss_shuffle" name="boss_shuffle" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="success" v-model="set.enemy_shuffle" name="enemy_shuffle" generator="base" :prefix="prefix" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="false">
|
||||
<template #header>
|
||||
<b>Dungeon Item Shuffle:</b>
|
||||
</template>
|
||||
<SettingPicker color="warning" v-model="set.small_keys" name="small_keys" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="warning" v-model="set.big_keys" name="big_keys" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="warning" v-model="set.maps" name="maps" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="warning" v-model="set.compasses" name="compasses" generator="base" :prefix="prefix" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="false">
|
||||
<template #header>
|
||||
<b>Other Pool Settings:</b>
|
||||
</template>
|
||||
<SettingPicker color="danger" v-model="set.shop_shuffle" name="shop_shuffle" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="danger" v-model="set.drop_shuffle" name="drop_shuffle" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="danger" v-model="set.pottery" name="pottery" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="danger" v-model="set.prize_shuffle" name="prize_shuffle" generator="base" :prefix="prefix" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="false">
|
||||
<template #header>
|
||||
<b>Item Settings:</b>
|
||||
</template>
|
||||
<SettingPicker color="primary" v-model="set.boots" name="boots" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="primary" v-model="set.flute" name="flute" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="primary" v-model="set.dark_rooms" name="dark_rooms" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="primary" v-model="set.bombs" name="bombs" generator="base" :prefix="prefix" />
|
||||
<SettingPicker color="primary" v-model="set.book" name="book" generator="base" :prefix="prefix" />
|
||||
</AccordionItem>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -5,6 +5,7 @@ import router from "./router";
|
||||
import "bootstrap/dist/css/bootstrap.min.css";
|
||||
import "bootstrap-icons/font/bootstrap-icons.css";
|
||||
import "vue-select/dist/vue-select.css";
|
||||
import "bootstrap/js/dist/tab.js";
|
||||
import "bootstrap";
|
||||
|
||||
import "./assets/main.css";
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { createRouter, createWebHistory } from "vue-router";
|
||||
import SeedView from "@/views/SeedView.vue";
|
||||
import MultiView from "@/views/MultiView.vue";
|
||||
import GenerateView from "@/views/GenerateView.vue";
|
||||
import GenerateMulti from "@/views/GenerateMulti.vue";
|
||||
import GenerateApr2025View from "@/views/GenerateApr2025View.vue";
|
||||
|
||||
const router = createRouter({
|
||||
@@ -12,6 +14,12 @@ const router = createRouter({
|
||||
component: GenerateView,
|
||||
alias: '/',
|
||||
},
|
||||
{
|
||||
path: '/multiworld',
|
||||
name: 'multiworld',
|
||||
component: GenerateMulti,
|
||||
alias: '/multi',
|
||||
},
|
||||
{
|
||||
path: '/generate/apr2025',
|
||||
component: GenerateApr2025View,
|
||||
@@ -21,6 +29,11 @@ const router = createRouter({
|
||||
name: 'seed',
|
||||
component: SeedView,
|
||||
},
|
||||
{
|
||||
path: '/multi/:id',
|
||||
name: 'multi',
|
||||
component: MultiView,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
106
src/views/GenerateMulti.vue
Normal file
106
src/views/GenerateMulti.vue
Normal file
@@ -0,0 +1,106 @@
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
import axios from "axios";
|
||||
import localforage from "localforage";
|
||||
import { Modal } from "bootstrap";
|
||||
|
||||
import SettingsPage from "@/components/SettingsPage.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
SettingsPage,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
worlds: [{}, {}, {}],
|
||||
worldCount: 3,
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
document.title = "ALttPR Multiworld"
|
||||
|
||||
await new Promise(r => setTimeout(r, 100));
|
||||
|
||||
for (var i = 0; i < this.worldCount; i++) {
|
||||
this.worlds[i].player_name = await localforage.getItem(`world_${i + 1}_setting_player_name`);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async playerNameUpdated(num) {
|
||||
await localforage.setItem(`world_${num + 1}_setting_player_name`, this.worlds[num].player_name);
|
||||
},
|
||||
async generate(race) {
|
||||
const settings = [];
|
||||
for (var i = 0; i < this.worldCount; i++) {
|
||||
const world = {
|
||||
randomizer: "base",
|
||||
race: race ? "race" : "normal"
|
||||
};
|
||||
for (const setting of Object.keys(this.worlds[i])) {
|
||||
world[setting] = this.worlds[i][setting];
|
||||
}
|
||||
if (!world.player_name) {
|
||||
world.player_name = `Player ${i + 1}`;
|
||||
}
|
||||
settings.push(world);
|
||||
}
|
||||
|
||||
await axios.post("/multiworld", settings)
|
||||
.then(response => {
|
||||
const id = response.data;
|
||||
this.$router.push(`/multi/${id}`);
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="card content-div m-3">
|
||||
<div class="card-header">
|
||||
Generate Multiworld
|
||||
</div>
|
||||
<ul class="nav nav-tabs">
|
||||
<li v-for="(n, idx) in worldCount" class="nav-item" role="presentation">
|
||||
<button class="nav-link" :class="{active: idx == 0}" data-bs-toggle="tab"
|
||||
:data-bs-target="`#world_page_${n}`" type="button" role="tab">
|
||||
{{ worlds[idx]?.player_name ?? n }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<template v-for="(n, idx) in worldCount">
|
||||
<div :id="`world_page_${n}`" class="tab-pane fade"
|
||||
:class="{show: idx == 0, active: idx == 0}" role="tabpanel">
|
||||
<div class="input-group ms-3 me-3 mt-3" style="width: inherit;">
|
||||
<label class="input-group-text" :for="`player_${n}_name`">
|
||||
Player {{ n }} Name:
|
||||
</label>
|
||||
<input type="text" class="form-control" :placeholder="`Player ${n}`"
|
||||
id="`player_${n}_name`" v-model="worlds[idx].player_name"
|
||||
@change="playerNameUpdated(idx)" />
|
||||
</div>
|
||||
<div id="settings" class="accordion accordion-flush">
|
||||
<SettingsPage v-model="worlds[idx]" :prefix="`world_${n}_`" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<div class="nav nav-pills nav-fill" role="group">
|
||||
<button type="button" class="m-1 nav-item btn btn-outline-danger"
|
||||
@click="generate(true);">
|
||||
Generate Race ROM
|
||||
</button>
|
||||
<button type="button" class="m-1 nav-item btn btn-outline-primary"
|
||||
@click="generate(false);">
|
||||
Generate ROM
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -4,36 +4,19 @@ import { defineComponent } from "vue";
|
||||
import axios from "axios";
|
||||
import { Modal } from "bootstrap";
|
||||
|
||||
import AccordionItem from "@/components/AccordionItem.vue";
|
||||
import PresetPicker from "@/components/PresetPicker.vue";
|
||||
import SettingPicker from "@/components/SettingPicker.vue";
|
||||
import SettingsPage from "@/components/SettingsPage.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
AccordionItem,
|
||||
PresetPicker,
|
||||
SettingPicker,
|
||||
SettingsPage,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
set: {},
|
||||
existingLocalPresets: [],
|
||||
newPresetName: "",
|
||||
replacePreset: null,
|
||||
modal: null,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
document.title = "ALttPRandomizer"
|
||||
this.modal = new Modal(document.getElementById("savePresetModal"), {});
|
||||
},
|
||||
watch: {
|
||||
set: {
|
||||
handler(newValue, oldValue) {
|
||||
this.$refs.preset.settingChanged(newValue);
|
||||
},
|
||||
deep: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async generate(race) {
|
||||
@@ -53,154 +36,17 @@ export default defineComponent({
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
presetSelected(preset) {
|
||||
for (const setting of Object.keys(this.set)) {
|
||||
if (preset[setting] != undefined) {
|
||||
this.set[setting] = preset[setting];
|
||||
}
|
||||
}
|
||||
},
|
||||
savePreset(names) {
|
||||
this.newPresetName = "";
|
||||
this.existingLocalPresets = names;
|
||||
this.modal.show();
|
||||
},
|
||||
async modalSavePreset() {
|
||||
const preset = JSON.parse(JSON.stringify(this.set));
|
||||
preset.display = this.newPresetName;
|
||||
if (this.replacePreset != null) {
|
||||
preset.display = this.existingLocalPresets[this.replacePreset];
|
||||
}
|
||||
await this.$refs.preset.savePreset(this.replacePreset, preset);
|
||||
this.modal.hide();
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="modal" tabindex="-1" id="savePresetModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Save Preset</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="input-group mb-3">
|
||||
<select v-model="replacePreset" class="form-select">
|
||||
<option :value="null" selected>New</option>
|
||||
<optgroup v-if="existingLocalPresets.length" label="Overwrite Preset:">
|
||||
<template v-for="(preset, idx) of existingLocalPresets">
|
||||
<option :value="idx">
|
||||
{{ preset }}
|
||||
</option>
|
||||
</template>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-3" v-if="replacePreset == null">
|
||||
<label class="input-group-text" for="new-preset-name">
|
||||
Name
|
||||
</label>
|
||||
<input type="text" class="form-control" placeholder="Display Name"
|
||||
id="new-preset-name" v-model="newPresetName" autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
<button :disabled="replacePreset == null && newPresetName.length == 0" type="button"
|
||||
class="btn btn-primary" @click="modalSavePreset">
|
||||
Save Preset
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card content-div m-3">
|
||||
<div class="card-header">
|
||||
Generate Seed
|
||||
</div>
|
||||
<div id="settings" class="accordion accordion-flush">
|
||||
<AccordionItem>
|
||||
<PresetPicker ref="preset" generator="base" @selected="presetSelected"
|
||||
@save="savePreset" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="true">
|
||||
<template #header>
|
||||
<b>World:</b>
|
||||
</template>
|
||||
<SettingPicker color="primary" v-model="set.mode" name="mode" generator="base" />
|
||||
<SettingPicker color="primary" v-model="set.weapons" name="weapons" generator="base" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="true">
|
||||
<template #header>
|
||||
<b>Goal:</b>
|
||||
</template>
|
||||
<SettingPicker color="success" v-model="set.goal" name="goal" generator="base" />
|
||||
<SettingPicker color="success" v-if="['ganon', 'fast_ganon'].includes(this.set.goal)"
|
||||
v-model="set.crystals_ganon" name="crystals_ganon" generator="base" />
|
||||
<SettingPicker color="success" v-model="set.crystals_gt" name="crystals_gt" generator="base" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="false">
|
||||
<template #header>
|
||||
<b>Entrance Shuffle:</b>
|
||||
</template>
|
||||
<SettingPicker color="warning" v-model="set.entrance_shuffle" name="entrance_shuffle" generator="base" />
|
||||
<SettingPicker color="warning" v-if="this.set.entrance_shuffle != 'vanilla'"
|
||||
v-model="set.skull_woods" name="skull_woods" generator="base" />
|
||||
<SettingPicker color="warning" v-if="this.set.entrance_shuffle != 'vanilla'"
|
||||
v-model="set.linked_drops" name="linked_drops" generator="base" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="false">
|
||||
<template #header>
|
||||
<b>Dungeon Shuffle:</b>
|
||||
</template>
|
||||
<SettingPicker color="danger" v-model="set.door_shuffle" name="door_shuffle" generator="base" />
|
||||
<SettingPicker color="danger" v-if="this.set.door_shuffle != 'vanilla'"
|
||||
v-model="set.door_lobbies" name="door_lobbies" generator="base" />
|
||||
<SettingPicker color="danger" v-if="this.set.door_shuffle != 'vanilla'"
|
||||
v-model="set.door_type_mode" name="door_type_mode" generator="base" />
|
||||
<SettingPicker color="danger" v-if="this.set.door_shuffle != 'vanilla'"
|
||||
v-model="set.trap_door_mode" name="trap_door_mode" generator="base" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="false">
|
||||
<template #header>
|
||||
<b>Enemizer:</b>
|
||||
</template>
|
||||
<SettingPicker color="success" v-model="set.boss_shuffle" name="boss_shuffle" generator="base" />
|
||||
<SettingPicker color="success" v-model="set.enemy_shuffle" name="enemy_shuffle" generator="base" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="false">
|
||||
<template #header>
|
||||
<b>Dungeon Item Shuffle:</b>
|
||||
</template>
|
||||
<SettingPicker color="warning" v-model="set.small_keys" name="small_keys" generator="base" />
|
||||
<SettingPicker color="warning" v-model="set.big_keys" name="big_keys" generator="base" />
|
||||
<SettingPicker color="warning" v-model="set.maps" name="maps" generator="base" />
|
||||
<SettingPicker color="warning" v-model="set.compasses" name="compasses" generator="base" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="false">
|
||||
<template #header>
|
||||
<b>Other Pool Settings:</b>
|
||||
</template>
|
||||
<SettingPicker color="danger" v-model="set.shop_shuffle" name="shop_shuffle" generator="base" />
|
||||
<SettingPicker color="danger" v-model="set.drop_shuffle" name="drop_shuffle" generator="base" />
|
||||
<SettingPicker color="danger" v-model="set.pottery" name="pottery" generator="base" />
|
||||
<SettingPicker color="danger" v-model="set.prize_shuffle" name="prize_shuffle" generator="base" />
|
||||
</AccordionItem>
|
||||
<AccordionItem :expanded="false">
|
||||
<template #header>
|
||||
<b>Item Settings:</b>
|
||||
</template>
|
||||
<SettingPicker color="primary" v-model="set.boots" name="boots" generator="base" />
|
||||
<SettingPicker color="primary" v-model="set.flute" name="flute" generator="base" />
|
||||
<SettingPicker color="primary" v-model="set.dark_rooms" name="dark_rooms" generator="base" />
|
||||
<SettingPicker color="primary" v-model="set.bombs" name="bombs" generator="base" />
|
||||
<SettingPicker color="primary" v-model="set.book" name="book" generator="base" />
|
||||
</AccordionItem>
|
||||
<SettingsPage v-model="set" prefix="" />
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<div class="nav nav-pills nav-fill" role="group">
|
||||
|
||||
15
src/views/MultiView.vue
Normal file
15
src/views/MultiView.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
import Multi from "@/components/Multi.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Multi,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Multi :id="$route.params.id" />
|
||||
</template>
|
||||
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
import Seed from '../components/Seed.vue';
|
||||
import Seed from "@/components/Seed.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
|
||||
Reference in New Issue
Block a user