Nuked the schema file and create my own. Works much better.
This commit is contained in:
parent
76f9717c99
commit
ad895f045c
|
@ -1,20 +1,8 @@
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
const gameSettings = document.getElementById('game-settings');
|
const gameSettings = document.getElementById('game-settings');
|
||||||
new Promise((resolve, reject) => {
|
Promise.all([fetchPlayerSettingsYaml(), fetchPlayerSettingsJson()]).then((results) => {
|
||||||
const ajax = new XMLHttpRequest();
|
|
||||||
ajax.onreadystatechange = () => {
|
|
||||||
if (ajax.readyState !== 4) { return; }
|
|
||||||
if (ajax.status !== 200) {
|
|
||||||
reject("Unable to fetch source yaml file.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
resolve(ajax.responseText);
|
|
||||||
};
|
|
||||||
ajax.open('GET', `${window.location.origin}/static/static/playerSettings.yaml` ,true);
|
|
||||||
ajax.send();
|
|
||||||
}).then((results) => {
|
|
||||||
// Load YAML into object
|
// Load YAML into object
|
||||||
const sourceData = jsyaml.load(results);
|
const sourceData = jsyaml.safeLoad(results[0], { json: true });
|
||||||
|
|
||||||
// Update localStorage with three settings objects. Preserve original objects if present.
|
// Update localStorage with three settings objects. Preserve original objects if present.
|
||||||
for (let i=1; i<=3; i++) {
|
for (let i=1; i<=3; i++) {
|
||||||
|
@ -23,6 +11,10 @@ window.addEventListener('load', () => {
|
||||||
localStorage.setItem(`gameSettings${i}`, JSON.stringify(updatedObj));
|
localStorage.setItem(`gameSettings${i}`, JSON.stringify(updatedObj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build the entire UI
|
||||||
|
buildUI(JSON.parse(results[1]));
|
||||||
|
|
||||||
|
// Populate the UI and add event listeners
|
||||||
populateSettings();
|
populateSettings();
|
||||||
document.getElementById('preset-number').addEventListener('change', populateSettings);
|
document.getElementById('preset-number').addEventListener('change', populateSettings);
|
||||||
gameSettings.addEventListener('change', handleOptionChange);
|
gameSettings.addEventListener('change', handleOptionChange);
|
||||||
|
@ -36,6 +28,34 @@ window.addEventListener('load', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const fetchPlayerSettingsYaml = () => new Promise((resolve, reject) => {
|
||||||
|
const ajax = new XMLHttpRequest();
|
||||||
|
ajax.onreadystatechange = () => {
|
||||||
|
if (ajax.readyState !== 4) { return; }
|
||||||
|
if (ajax.status !== 200) {
|
||||||
|
reject("Unable to fetch source yaml file.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(ajax.responseText);
|
||||||
|
};
|
||||||
|
ajax.open('GET', `${window.location.origin}/static/static/playerSettings.yaml` ,true);
|
||||||
|
ajax.send();
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchPlayerSettingsJson = () => new Promise((resolve, reject) => {
|
||||||
|
const ajax = new XMLHttpRequest();
|
||||||
|
ajax.onreadystatechange = () => {
|
||||||
|
if (ajax.readyState !== 4) { return; }
|
||||||
|
if (ajax.status !== 200) {
|
||||||
|
reject('Unable to fetch JSON schema file');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(ajax.responseText);
|
||||||
|
};
|
||||||
|
ajax.open('GET', `${window.location.origin}/static/static/playerSettings.json`);
|
||||||
|
ajax.send();
|
||||||
|
});
|
||||||
|
|
||||||
const handleOptionChange = (event) => {
|
const handleOptionChange = (event) => {
|
||||||
if(!event.target.matches('.setting')) { return; }
|
if(!event.target.matches('.setting')) { return; }
|
||||||
const presetNumber = document.getElementById('preset-number').value;
|
const presetNumber = document.getElementById('preset-number').value;
|
||||||
|
@ -73,7 +93,6 @@ const populateSettings = () => {
|
||||||
settingsInputs.forEach((input) => {
|
settingsInputs.forEach((input) => {
|
||||||
const settingString = input.getAttribute('data-setting');
|
const settingString = input.getAttribute('data-setting');
|
||||||
const settingValue = getSettingValue(settings, settingString);
|
const settingValue = getSettingValue(settings, settingString);
|
||||||
console.info(`${settingString}: ${settingValue}`);
|
|
||||||
if(settingValue !== false){
|
if(settingValue !== false){
|
||||||
input.value = settingValue;
|
input.value = settingValue;
|
||||||
document.getElementById(settingString).innerText = settingValue;
|
document.getElementById(settingString).innerText = settingValue;
|
||||||
|
@ -99,3 +118,98 @@ const getSettingValue = (settings, keyString) => {
|
||||||
});
|
});
|
||||||
return currentVal;
|
return currentVal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const buildUI = (settings) => {
|
||||||
|
const settingsWrapper = document.getElementById('settings-wrapper');
|
||||||
|
Object.values(settings).forEach((setting) => {
|
||||||
|
if (typeof(setting.inputType) === 'undefined' || !setting.inputType){
|
||||||
|
console.error(setting);
|
||||||
|
throw new Error('Setting with no inputType specified.');
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(setting.inputType){
|
||||||
|
case 'text':
|
||||||
|
// Currently, all text input is handled manually because there is very little of it
|
||||||
|
return;
|
||||||
|
case 'range':
|
||||||
|
buildRangeSettings(settingsWrapper, setting);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
console.error(setting);
|
||||||
|
throw new Error('Unhandled inputType specified.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildRangeSettings = (parentElement, settings) => {
|
||||||
|
// Ensure we are operating on a range-specific setting
|
||||||
|
if(typeof(settings.inputType) === 'undefined' || settings.inputType !== 'range'){
|
||||||
|
throw new Error('Invalid input type provided to buildRangeSettings func.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const settingWrapper = document.createElement('div');
|
||||||
|
settingWrapper.className = 'setting-wrapper';
|
||||||
|
|
||||||
|
if(typeof(settings.friendlyName) !== 'undefined' && settings.friendlyName){
|
||||||
|
const sectionTitle = document.createElement('span');
|
||||||
|
sectionTitle.className = 'title-span';
|
||||||
|
sectionTitle.innerText = settings.friendlyName;
|
||||||
|
settingWrapper.appendChild(sectionTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(settings.description){
|
||||||
|
const description = document.createElement('span');
|
||||||
|
description.className = 'description-span';
|
||||||
|
description.innerText = settings.description;
|
||||||
|
settingWrapper.appendChild(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create table
|
||||||
|
const optionSetTable = document.createElement('table');
|
||||||
|
optionSetTable.className = 'option-set';
|
||||||
|
|
||||||
|
// Create table body
|
||||||
|
const tbody = document.createElement('tbody');
|
||||||
|
Object.keys(settings.subOptions).forEach((setting) => {
|
||||||
|
// Overwrite setting key name with real object
|
||||||
|
setting = settings.subOptions[setting];
|
||||||
|
const settingId = (Math.random() * 1000000).toString();
|
||||||
|
|
||||||
|
// Create rows for each option
|
||||||
|
const optionRow = document.createElement('tr');
|
||||||
|
|
||||||
|
// Option name td
|
||||||
|
const optionName = document.createElement('td');
|
||||||
|
optionName.className = 'option-name';
|
||||||
|
const optionLabel = document.createElement('label');
|
||||||
|
optionLabel.setAttribute('for', settingId);
|
||||||
|
optionLabel.innerText = setting.friendlyName;
|
||||||
|
optionName.appendChild(optionLabel);
|
||||||
|
optionRow.appendChild(optionName);
|
||||||
|
|
||||||
|
// Option value td
|
||||||
|
const optionValue = document.createElement('td');
|
||||||
|
optionValue.className = 'option-value';
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.className = 'setting';
|
||||||
|
input.setAttribute('id', settingId);
|
||||||
|
input.setAttribute('type', 'range');
|
||||||
|
input.setAttribute('min', '0');
|
||||||
|
input.setAttribute('max', '100');
|
||||||
|
input.setAttribute('data-setting', setting.keyString);
|
||||||
|
input.value = setting.defaultValue;
|
||||||
|
optionValue.appendChild(input);
|
||||||
|
const valueDisplay = document.createElement('span');
|
||||||
|
valueDisplay.setAttribute('id', setting.keyString);
|
||||||
|
valueDisplay.innerText = setting.defaultValue;
|
||||||
|
optionValue.appendChild(valueDisplay);
|
||||||
|
optionRow.appendChild(optionValue);
|
||||||
|
tbody.appendChild(optionRow);
|
||||||
|
});
|
||||||
|
|
||||||
|
optionSetTable.appendChild(tbody);
|
||||||
|
settingWrapper.appendChild(optionSetTable);
|
||||||
|
parentElement.appendChild(settingWrapper);
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildSelectSettings = (parentElement, settings) => {};
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
{
|
||||||
|
"description": {
|
||||||
|
"keyString": "description",
|
||||||
|
"friendlyName": "Description",
|
||||||
|
"inputType": "text",
|
||||||
|
"description": "A short description of this preset. Useful if you have multiple files",
|
||||||
|
"defaultValue": "Preset Name"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"keyString": "name",
|
||||||
|
"friendlyName": "Player Name",
|
||||||
|
"inputType": "text",
|
||||||
|
"description": "Displayed in-game. Spaces will be replaced with underscores.",
|
||||||
|
"defaultValue": "Your Name"
|
||||||
|
},
|
||||||
|
"glitches_required": {
|
||||||
|
"keyString": "glitches_required",
|
||||||
|
"friendlyName": "Glitches Required",
|
||||||
|
"description": "Determine the logic required to complete the seed.",
|
||||||
|
"inputType": "range",
|
||||||
|
"subOptions": {
|
||||||
|
"none": {
|
||||||
|
"keyString": "glitches_required.none",
|
||||||
|
"friendlyName": "None",
|
||||||
|
"description": "No glitches required.",
|
||||||
|
"defaultValue": 50
|
||||||
|
},
|
||||||
|
"minor_glitches": {
|
||||||
|
"keyString": "glitches_required.minor_glitches",
|
||||||
|
"friendlyName": "Minor Glitches",
|
||||||
|
"description": "Puts fake flipper, water-walk, super bunny, etc into logic",
|
||||||
|
"defaultValue": 0
|
||||||
|
},
|
||||||
|
"overworld_glitches": {
|
||||||
|
"keyString": "glitches_required.overworld_glitches",
|
||||||
|
"friendlyName": "Overworld Glitches",
|
||||||
|
"description": "Assumes the player has knowledge of both overworld major glitches (boots clips, mirror clips) and minor glitches (fake flipper, super bunny shenanigans, water walk and etc.)",
|
||||||
|
"defaultValue": 0
|
||||||
|
},
|
||||||
|
"no_logic": {
|
||||||
|
"keyString": "glitches_required.no_logic",
|
||||||
|
"friendlyName": "No Logic",
|
||||||
|
"description": "Your items are placed with no regard to any logic. Your Fire Rod could be on your Trinexx.",
|
||||||
|
"defaultValue": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"map_shuffle": {
|
||||||
|
"keyString": "map_shuffle",
|
||||||
|
"friendlyName": "Map Shuffle",
|
||||||
|
"description": "Shuffle dungeon maps into the world and other dungeons, including other players' worlds.",
|
||||||
|
"inputType": "range",
|
||||||
|
"subOptions": {
|
||||||
|
"off": {
|
||||||
|
"keyString": "map_shuffle.off",
|
||||||
|
"friendlyName": "Off",
|
||||||
|
"description": "Disable map shuffle.",
|
||||||
|
"defaultValue": 50
|
||||||
|
},
|
||||||
|
"on": {
|
||||||
|
"keyString": "map_shuffle.on",
|
||||||
|
"friendlyName": "On",
|
||||||
|
"description": "Enable map shuffle.",
|
||||||
|
"defaultValue": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compass_shuffle": {
|
||||||
|
"keyString": "compass_shuffle",
|
||||||
|
"friendlyName": "Compass Shuffle",
|
||||||
|
"description": "Shuffle compasses into the world and other dungeons, including other players' worlds",
|
||||||
|
"inputType": "range",
|
||||||
|
"subOptions": {
|
||||||
|
"off": {
|
||||||
|
"keyString": "compass_shuffle.off",
|
||||||
|
"friendlyName": "Off",
|
||||||
|
"description": "Disable compass shuffle.",
|
||||||
|
"defaultValue": 50
|
||||||
|
},
|
||||||
|
"on": {
|
||||||
|
"keyString": "compass_shuffle.on",
|
||||||
|
"friendlyName": "On",
|
||||||
|
"description": "Enable compass shuffle.",
|
||||||
|
"defaultValue": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -10,8 +10,19 @@
|
||||||
padding-right: 0.25rem;
|
padding-right: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#game-settings #instructions{
|
#game-settings .instructions{
|
||||||
text-align: center;
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#game-settings #settings-wrapper .setting-wrapper{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#game-settings #settings-wrapper .setting-wrapper .title-span{
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
#game-settings #settings-wrapper{
|
#game-settings #settings-wrapper{
|
||||||
|
|
|
@ -9,14 +9,15 @@
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div id="game-settings" class="main-content">
|
<div id="game-settings" class="main-content">
|
||||||
<h3>Game Settings</h3>
|
<h3>Player Settings</h3>
|
||||||
<div id="instructions">
|
<div id="instructions">
|
||||||
This page is used to configure your game settings. You have three presets you can control, which
|
This page is used to configure your player settings. You have three presets you can control, which
|
||||||
you can access using the dropdown menu below. These settings will be usable when generating a
|
you can access using the dropdown menu below. These settings will be usable when generating a
|
||||||
single player game, or you can export them to a <code>.yaml</code> file and use them in a multiworld.
|
single player game, or you can export them to a <code>.yaml</code> file and use them in a multiworld.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="settings-wrapper">
|
<div id="settings-wrapper">
|
||||||
|
<div class="setting-wrapper">
|
||||||
Choose a preset and optionally assign it a nickname, which will be used as the file's description if
|
Choose a preset and optionally assign it a nickname, which will be used as the file's description if
|
||||||
you download it.
|
you download it.
|
||||||
<table class="option-set">
|
<table class="option-set">
|
||||||
|
@ -43,6 +44,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
Choose a name you want to represent you in-game. This will appear when you send items
|
Choose a name you want to represent you in-game. This will appear when you send items
|
||||||
to other people in multiworld games.
|
to other people in multiworld games.
|
||||||
|
@ -58,73 +60,6 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
Glitches Required - Allows the generator to place required items in locations which require knowledge
|
|
||||||
of glitches.
|
|
||||||
<table class="option-set">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td class="option-name">
|
|
||||||
<label for="glitches-required-none">None:</label>
|
|
||||||
</td>
|
|
||||||
<td class="option-value">
|
|
||||||
<input id="glitches-required-none"
|
|
||||||
data-setting="glitches_required.none"
|
|
||||||
class="setting"
|
|
||||||
type="range"
|
|
||||||
min="0"
|
|
||||||
max="100"
|
|
||||||
/>
|
|
||||||
<span id="glitches_required.none"></span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="option-name">
|
|
||||||
<label for="glitches-required-minor">Minor Glitches:</label>
|
|
||||||
</td>
|
|
||||||
<td class="option-value">
|
|
||||||
<input id="glitches-required-minor"
|
|
||||||
data-setting="glitches_required.minor_glitches"
|
|
||||||
class="setting"
|
|
||||||
type="range"
|
|
||||||
min="0"
|
|
||||||
max="100"
|
|
||||||
/>
|
|
||||||
<span id="glitches_required.minor_glitches"></span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="option-name">
|
|
||||||
<label for="glitches-required-overworld">Overworld Glitches:</label>
|
|
||||||
</td>
|
|
||||||
<td class="option-value">
|
|
||||||
<input id="glitches-required-overworld"
|
|
||||||
data-setting="glitches_required.overworld_glitches"
|
|
||||||
class="setting"
|
|
||||||
type="range"
|
|
||||||
min="0"
|
|
||||||
max="100"
|
|
||||||
/>
|
|
||||||
<span id="glitches_required.overworld_glitches"></span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="option-name">
|
|
||||||
<label for="glitches-required-no-logic">No Logic:</label>
|
|
||||||
</td>
|
|
||||||
<td class="option-value">
|
|
||||||
<input id="glitches-required-no-logic"
|
|
||||||
data-setting="glitches_required.no_logic"
|
|
||||||
class="setting"
|
|
||||||
type="range"
|
|
||||||
min="0"
|
|
||||||
max="100"
|
|
||||||
/>
|
|
||||||
<span id="glitches_required.no_logic"></span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
Loading…
Reference in New Issue