[WebHost] Add support for items-list, locations-list, and custom-list option types to weighted-settings (#1614)
* Add support for items-list, locations-list, and custom-list option types to weighted-settings * Fix subclass detection for `items-list`, `locations-list`, and `custom-list` in weighted-settings * Move specially handled options alongside each other in the UI, and split them into logical groupings * Fix header text and location for Priority an Exclusion locations * Add universally supported "random" option to `Choice` and `TextChoice` options in weighted-settings * Update description text for exclusion items to clarify they also prevent helpful items. * Be technically correct and call them `useful` items.
This commit is contained in:
parent
639606e0be
commit
a5373e3672
|
@ -11,7 +11,7 @@ from Utils import __version__, local_path
|
||||||
from worlds.AutoWorld import AutoWorldRegister
|
from worlds.AutoWorld import AutoWorldRegister
|
||||||
|
|
||||||
handled_in_js = {"start_inventory", "local_items", "non_local_items", "start_hints", "start_location_hints",
|
handled_in_js = {"start_inventory", "local_items", "non_local_items", "start_hints", "start_location_hints",
|
||||||
"exclude_locations"}
|
"exclude_locations", "priority_locations"}
|
||||||
|
|
||||||
|
|
||||||
def create():
|
def create():
|
||||||
|
@ -88,7 +88,7 @@ def create():
|
||||||
if option_name in handled_in_js:
|
if option_name in handled_in_js:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
elif option.options:
|
elif issubclass(option, Options.Choice) or issubclass(option, Options.TextChoice):
|
||||||
game_options[option_name] = this_option = {
|
game_options[option_name] = this_option = {
|
||||||
"type": "select",
|
"type": "select",
|
||||||
"displayName": option.display_name if hasattr(option, "display_name") else option_name,
|
"displayName": option.display_name if hasattr(option, "display_name") else option_name,
|
||||||
|
@ -97,6 +97,7 @@ def create():
|
||||||
"options": []
|
"options": []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
has_random_option = False
|
||||||
for sub_option_id, sub_option_name in option.name_lookup.items():
|
for sub_option_id, sub_option_name in option.name_lookup.items():
|
||||||
this_option["options"].append({
|
this_option["options"].append({
|
||||||
"name": option.get_option_name(sub_option_id),
|
"name": option.get_option_name(sub_option_id),
|
||||||
|
@ -106,6 +107,15 @@ def create():
|
||||||
if sub_option_id == option.default:
|
if sub_option_id == option.default:
|
||||||
this_option["defaultValue"] = sub_option_name
|
this_option["defaultValue"] = sub_option_name
|
||||||
|
|
||||||
|
if sub_option_name == "random":
|
||||||
|
has_random_option = True
|
||||||
|
|
||||||
|
if not has_random_option:
|
||||||
|
this_option["options"].append({
|
||||||
|
"name": "random",
|
||||||
|
"value": 'random',
|
||||||
|
})
|
||||||
|
|
||||||
if option.default == "random":
|
if option.default == "random":
|
||||||
this_option["defaultValue"] = "random"
|
this_option["defaultValue"] = "random"
|
||||||
|
|
||||||
|
@ -126,21 +136,21 @@ def create():
|
||||||
for key, val in option.special_range_names.items():
|
for key, val in option.special_range_names.items():
|
||||||
game_options[option_name]["value_names"][key] = val
|
game_options[option_name]["value_names"][key] = val
|
||||||
|
|
||||||
elif getattr(option, "verify_item_name", False):
|
elif issubclass(option, Options.ItemSet):
|
||||||
game_options[option_name] = {
|
game_options[option_name] = {
|
||||||
"type": "items-list",
|
"type": "items-list",
|
||||||
"displayName": option.display_name if hasattr(option, "display_name") else option_name,
|
"displayName": option.display_name if hasattr(option, "display_name") else option_name,
|
||||||
"description": get_html_doc(option),
|
"description": get_html_doc(option),
|
||||||
}
|
}
|
||||||
|
|
||||||
elif getattr(option, "verify_location_name", False):
|
elif issubclass(option, Options.LocationSet):
|
||||||
game_options[option_name] = {
|
game_options[option_name] = {
|
||||||
"type": "locations-list",
|
"type": "locations-list",
|
||||||
"displayName": option.display_name if hasattr(option, "display_name") else option_name,
|
"displayName": option.display_name if hasattr(option, "display_name") else option_name,
|
||||||
"description": get_html_doc(option),
|
"description": get_html_doc(option),
|
||||||
}
|
}
|
||||||
|
|
||||||
elif issubclass(option, Options.OptionList) or issubclass(option, Options.OptionSet):
|
elif issubclass(option, Options.VerifyKeys):
|
||||||
if option.valid_keys:
|
if option.valid_keys:
|
||||||
game_options[option_name] = {
|
game_options[option_name] = {
|
||||||
"type": "custom-list",
|
"type": "custom-list",
|
||||||
|
|
|
@ -101,6 +101,7 @@ const createDefaultSettings = (settingData) => {
|
||||||
|
|
||||||
newSettings[game].start_inventory = {};
|
newSettings[game].start_inventory = {};
|
||||||
newSettings[game].exclude_locations = [];
|
newSettings[game].exclude_locations = [];
|
||||||
|
newSettings[game].priority_locations = [];
|
||||||
newSettings[game].local_items = [];
|
newSettings[game].local_items = [];
|
||||||
newSettings[game].non_local_items = [];
|
newSettings[game].non_local_items = [];
|
||||||
newSettings[game].start_hints = [];
|
newSettings[game].start_hints = [];
|
||||||
|
@ -136,21 +137,28 @@ const buildUI = (settingData) => {
|
||||||
expandButton.classList.add('invisible');
|
expandButton.classList.add('invisible');
|
||||||
gameDiv.appendChild(expandButton);
|
gameDiv.appendChild(expandButton);
|
||||||
|
|
||||||
const weightedSettingsDiv = buildWeightedSettingsDiv(game, settingData.games[game].gameSettings);
|
settingData.games[game].gameItems.sort((a, b) => (a > b ? 1 : (a < b ? -1 : 0)));
|
||||||
|
settingData.games[game].gameLocations.sort((a, b) => (a > b ? 1 : (a < b ? -1 : 0)));
|
||||||
|
|
||||||
|
const weightedSettingsDiv = buildWeightedSettingsDiv(game, settingData.games[game].gameSettings,
|
||||||
|
settingData.games[game].gameItems, settingData.games[game].gameLocations);
|
||||||
gameDiv.appendChild(weightedSettingsDiv);
|
gameDiv.appendChild(weightedSettingsDiv);
|
||||||
|
|
||||||
const itemsDiv = buildItemsDiv(game, settingData.games[game].gameItems);
|
const itemPoolDiv = buildItemsDiv(game, settingData.games[game].gameItems);
|
||||||
gameDiv.appendChild(itemsDiv);
|
gameDiv.appendChild(itemPoolDiv);
|
||||||
|
|
||||||
const hintsDiv = buildHintsDiv(game, settingData.games[game].gameItems, settingData.games[game].gameLocations);
|
const hintsDiv = buildHintsDiv(game, settingData.games[game].gameItems, settingData.games[game].gameLocations);
|
||||||
gameDiv.appendChild(hintsDiv);
|
gameDiv.appendChild(hintsDiv);
|
||||||
|
|
||||||
|
const locationsDiv = buildLocationsDiv(game, settingData.games[game].gameLocations);
|
||||||
|
gameDiv.appendChild(locationsDiv);
|
||||||
|
|
||||||
gamesWrapper.appendChild(gameDiv);
|
gamesWrapper.appendChild(gameDiv);
|
||||||
|
|
||||||
collapseButton.addEventListener('click', () => {
|
collapseButton.addEventListener('click', () => {
|
||||||
collapseButton.classList.add('invisible');
|
collapseButton.classList.add('invisible');
|
||||||
weightedSettingsDiv.classList.add('invisible');
|
weightedSettingsDiv.classList.add('invisible');
|
||||||
itemsDiv.classList.add('invisible');
|
itemPoolDiv.classList.add('invisible');
|
||||||
hintsDiv.classList.add('invisible');
|
hintsDiv.classList.add('invisible');
|
||||||
expandButton.classList.remove('invisible');
|
expandButton.classList.remove('invisible');
|
||||||
});
|
});
|
||||||
|
@ -158,7 +166,7 @@ const buildUI = (settingData) => {
|
||||||
expandButton.addEventListener('click', () => {
|
expandButton.addEventListener('click', () => {
|
||||||
collapseButton.classList.remove('invisible');
|
collapseButton.classList.remove('invisible');
|
||||||
weightedSettingsDiv.classList.remove('invisible');
|
weightedSettingsDiv.classList.remove('invisible');
|
||||||
itemsDiv.classList.remove('invisible');
|
itemPoolDiv.classList.remove('invisible');
|
||||||
hintsDiv.classList.remove('invisible');
|
hintsDiv.classList.remove('invisible');
|
||||||
expandButton.classList.add('invisible');
|
expandButton.classList.add('invisible');
|
||||||
});
|
});
|
||||||
|
@ -226,7 +234,7 @@ const buildGameChoice = (games) => {
|
||||||
gameChoiceDiv.appendChild(table);
|
gameChoiceDiv.appendChild(table);
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildWeightedSettingsDiv = (game, settings) => {
|
const buildWeightedSettingsDiv = (game, settings, gameItems, gameLocations) => {
|
||||||
const currentSettings = JSON.parse(localStorage.getItem('weighted-settings'));
|
const currentSettings = JSON.parse(localStorage.getItem('weighted-settings'));
|
||||||
const settingsWrapper = document.createElement('div');
|
const settingsWrapper = document.createElement('div');
|
||||||
settingsWrapper.classList.add('settings-wrapper');
|
settingsWrapper.classList.add('settings-wrapper');
|
||||||
|
@ -268,7 +276,7 @@ const buildWeightedSettingsDiv = (game, settings) => {
|
||||||
range.setAttribute('data-type', setting.type);
|
range.setAttribute('data-type', setting.type);
|
||||||
range.setAttribute('min', 0);
|
range.setAttribute('min', 0);
|
||||||
range.setAttribute('max', 50);
|
range.setAttribute('max', 50);
|
||||||
range.addEventListener('change', updateGameSetting);
|
range.addEventListener('change', updateRangeSetting);
|
||||||
range.value = currentSettings[game][settingName][option.value];
|
range.value = currentSettings[game][settingName][option.value];
|
||||||
tdMiddle.appendChild(range);
|
tdMiddle.appendChild(range);
|
||||||
tr.appendChild(tdMiddle);
|
tr.appendChild(tdMiddle);
|
||||||
|
@ -309,7 +317,7 @@ const buildWeightedSettingsDiv = (game, settings) => {
|
||||||
range.setAttribute('data-option', i);
|
range.setAttribute('data-option', i);
|
||||||
range.setAttribute('min', 0);
|
range.setAttribute('min', 0);
|
||||||
range.setAttribute('max', 50);
|
range.setAttribute('max', 50);
|
||||||
range.addEventListener('change', updateGameSetting);
|
range.addEventListener('change', updateRangeSetting);
|
||||||
range.value = currentSettings[game][settingName][i] || 0;
|
range.value = currentSettings[game][settingName][i] || 0;
|
||||||
tdMiddle.appendChild(range);
|
tdMiddle.appendChild(range);
|
||||||
tr.appendChild(tdMiddle);
|
tr.appendChild(tdMiddle);
|
||||||
|
@ -377,7 +385,7 @@ const buildWeightedSettingsDiv = (game, settings) => {
|
||||||
range.setAttribute('data-option', option);
|
range.setAttribute('data-option', option);
|
||||||
range.setAttribute('min', 0);
|
range.setAttribute('min', 0);
|
||||||
range.setAttribute('max', 50);
|
range.setAttribute('max', 50);
|
||||||
range.addEventListener('change', updateGameSetting);
|
range.addEventListener('change', updateRangeSetting);
|
||||||
range.value = currentSettings[game][settingName][parseInt(option, 10)];
|
range.value = currentSettings[game][settingName][parseInt(option, 10)];
|
||||||
tdMiddle.appendChild(range);
|
tdMiddle.appendChild(range);
|
||||||
tr.appendChild(tdMiddle);
|
tr.appendChild(tdMiddle);
|
||||||
|
@ -428,7 +436,7 @@ const buildWeightedSettingsDiv = (game, settings) => {
|
||||||
range.setAttribute('data-option', option);
|
range.setAttribute('data-option', option);
|
||||||
range.setAttribute('min', 0);
|
range.setAttribute('min', 0);
|
||||||
range.setAttribute('max', 50);
|
range.setAttribute('max', 50);
|
||||||
range.addEventListener('change', updateGameSetting);
|
range.addEventListener('change', updateRangeSetting);
|
||||||
range.value = currentSettings[game][settingName][parseInt(option, 10)];
|
range.value = currentSettings[game][settingName][parseInt(option, 10)];
|
||||||
tdMiddle.appendChild(range);
|
tdMiddle.appendChild(range);
|
||||||
tr.appendChild(tdMiddle);
|
tr.appendChild(tdMiddle);
|
||||||
|
@ -475,7 +483,7 @@ const buildWeightedSettingsDiv = (game, settings) => {
|
||||||
range.setAttribute('data-option', option);
|
range.setAttribute('data-option', option);
|
||||||
range.setAttribute('min', 0);
|
range.setAttribute('min', 0);
|
||||||
range.setAttribute('max', 50);
|
range.setAttribute('max', 50);
|
||||||
range.addEventListener('change', updateGameSetting);
|
range.addEventListener('change', updateRangeSetting);
|
||||||
range.value = currentSettings[game][settingName][option];
|
range.value = currentSettings[game][settingName][option];
|
||||||
tdMiddle.appendChild(range);
|
tdMiddle.appendChild(range);
|
||||||
tr.appendChild(tdMiddle);
|
tr.appendChild(tdMiddle);
|
||||||
|
@ -493,15 +501,108 @@ const buildWeightedSettingsDiv = (game, settings) => {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'items-list':
|
case 'items-list':
|
||||||
// TODO
|
const itemsList = document.createElement('div');
|
||||||
|
itemsList.classList.add('simple-list');
|
||||||
|
|
||||||
|
Object.values(gameItems).forEach((item) => {
|
||||||
|
const itemRow = document.createElement('div');
|
||||||
|
itemRow.classList.add('list-row');
|
||||||
|
|
||||||
|
const itemLabel = document.createElement('label');
|
||||||
|
itemLabel.setAttribute('for', `${game}-${settingName}-${item}`)
|
||||||
|
|
||||||
|
const itemCheckbox = document.createElement('input');
|
||||||
|
itemCheckbox.setAttribute('id', `${game}-${settingName}-${item}`);
|
||||||
|
itemCheckbox.setAttribute('type', 'checkbox');
|
||||||
|
itemCheckbox.setAttribute('data-game', game);
|
||||||
|
itemCheckbox.setAttribute('data-setting', settingName);
|
||||||
|
itemCheckbox.setAttribute('data-option', item.toString());
|
||||||
|
itemCheckbox.addEventListener('change', updateListSetting);
|
||||||
|
if (currentSettings[game][settingName].includes(item)) {
|
||||||
|
itemCheckbox.setAttribute('checked', '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemName = document.createElement('span');
|
||||||
|
itemName.innerText = item.toString();
|
||||||
|
|
||||||
|
itemLabel.appendChild(itemCheckbox);
|
||||||
|
itemLabel.appendChild(itemName);
|
||||||
|
|
||||||
|
itemRow.appendChild(itemLabel);
|
||||||
|
itemsList.appendChild((itemRow));
|
||||||
|
});
|
||||||
|
|
||||||
|
settingWrapper.appendChild(itemsList);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'locations-list':
|
case 'locations-list':
|
||||||
// TODO
|
const locationsList = document.createElement('div');
|
||||||
|
locationsList.classList.add('simple-list');
|
||||||
|
|
||||||
|
Object.values(gameLocations).forEach((location) => {
|
||||||
|
const locationRow = document.createElement('div');
|
||||||
|
locationRow.classList.add('list-row');
|
||||||
|
|
||||||
|
const locationLabel = document.createElement('label');
|
||||||
|
locationLabel.setAttribute('for', `${game}-${settingName}-${location}`)
|
||||||
|
|
||||||
|
const locationCheckbox = document.createElement('input');
|
||||||
|
locationCheckbox.setAttribute('id', `${game}-${settingName}-${location}`);
|
||||||
|
locationCheckbox.setAttribute('type', 'checkbox');
|
||||||
|
locationCheckbox.setAttribute('data-game', game);
|
||||||
|
locationCheckbox.setAttribute('data-setting', settingName);
|
||||||
|
locationCheckbox.setAttribute('data-option', location.toString());
|
||||||
|
locationCheckbox.addEventListener('change', updateListSetting);
|
||||||
|
if (currentSettings[game][settingName].includes(location)) {
|
||||||
|
locationCheckbox.setAttribute('checked', '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
const locationName = document.createElement('span');
|
||||||
|
locationName.innerText = location.toString();
|
||||||
|
|
||||||
|
locationLabel.appendChild(locationCheckbox);
|
||||||
|
locationLabel.appendChild(locationName);
|
||||||
|
|
||||||
|
locationRow.appendChild(locationLabel);
|
||||||
|
locationsList.appendChild((locationRow));
|
||||||
|
});
|
||||||
|
|
||||||
|
settingWrapper.appendChild(locationsList);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'custom-list':
|
case 'custom-list':
|
||||||
// TODO
|
const customList = document.createElement('div');
|
||||||
|
customList.classList.add('simple-list');
|
||||||
|
|
||||||
|
Object.values(settings[settingName].options).forEach((listItem) => {
|
||||||
|
const customListRow = document.createElement('div');
|
||||||
|
customListRow.classList.add('list-row');
|
||||||
|
|
||||||
|
const customItemLabel = document.createElement('label');
|
||||||
|
customItemLabel.setAttribute('for', `${game}-${settingName}-${listItem}`)
|
||||||
|
|
||||||
|
const customItemCheckbox = document.createElement('input');
|
||||||
|
customItemCheckbox.setAttribute('id', `${game}-${settingName}-${listItem}`);
|
||||||
|
customItemCheckbox.setAttribute('type', 'checkbox');
|
||||||
|
customItemCheckbox.setAttribute('data-game', game);
|
||||||
|
customItemCheckbox.setAttribute('data-setting', settingName);
|
||||||
|
customItemCheckbox.setAttribute('data-option', listItem.toString());
|
||||||
|
customItemCheckbox.addEventListener('change', updateListSetting);
|
||||||
|
if (currentSettings[game][settingName].includes(listItem)) {
|
||||||
|
customItemCheckbox.setAttribute('checked', '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
const customItemName = document.createElement('span');
|
||||||
|
customItemName.innerText = listItem.toString();
|
||||||
|
|
||||||
|
customItemLabel.appendChild(customItemCheckbox);
|
||||||
|
customItemLabel.appendChild(customItemName);
|
||||||
|
|
||||||
|
customListRow.appendChild(customItemLabel);
|
||||||
|
customList.appendChild((customListRow));
|
||||||
|
});
|
||||||
|
|
||||||
|
settingWrapper.appendChild(customList);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -727,21 +828,22 @@ const buildHintsDiv = (game, items, locations) => {
|
||||||
const hintsDescription = document.createElement('p');
|
const hintsDescription = document.createElement('p');
|
||||||
hintsDescription.classList.add('setting-description');
|
hintsDescription.classList.add('setting-description');
|
||||||
hintsDescription.innerText = 'Choose any items or locations to begin the game with the knowledge of where those ' +
|
hintsDescription.innerText = 'Choose any items or locations to begin the game with the knowledge of where those ' +
|
||||||
' items are, or what those locations contain. Excluded locations will not contain progression items.';
|
' items are, or what those locations contain.';
|
||||||
hintsDiv.appendChild(hintsDescription);
|
hintsDiv.appendChild(hintsDescription);
|
||||||
|
|
||||||
const itemHintsContainer = document.createElement('div');
|
const itemHintsContainer = document.createElement('div');
|
||||||
itemHintsContainer.classList.add('hints-container');
|
itemHintsContainer.classList.add('hints-container');
|
||||||
|
|
||||||
|
// Item Hints
|
||||||
const itemHintsWrapper = document.createElement('div');
|
const itemHintsWrapper = document.createElement('div');
|
||||||
itemHintsWrapper.classList.add('hints-wrapper');
|
itemHintsWrapper.classList.add('hints-wrapper');
|
||||||
itemHintsWrapper.innerText = 'Starting Item Hints';
|
itemHintsWrapper.innerText = 'Starting Item Hints';
|
||||||
|
|
||||||
const itemHintsDiv = document.createElement('div');
|
const itemHintsDiv = document.createElement('div');
|
||||||
itemHintsDiv.classList.add('item-container');
|
itemHintsDiv.classList.add('simple-list');
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
const itemDiv = document.createElement('div');
|
const itemRow = document.createElement('div');
|
||||||
itemDiv.classList.add('hint-div');
|
itemRow.classList.add('list-row');
|
||||||
|
|
||||||
const itemLabel = document.createElement('label');
|
const itemLabel = document.createElement('label');
|
||||||
itemLabel.setAttribute('for', `${game}-start_hints-${item}`);
|
itemLabel.setAttribute('for', `${game}-start_hints-${item}`);
|
||||||
|
@ -755,29 +857,30 @@ const buildHintsDiv = (game, items, locations) => {
|
||||||
if (currentSettings[game].start_hints.includes(item)) {
|
if (currentSettings[game].start_hints.includes(item)) {
|
||||||
itemCheckbox.setAttribute('checked', 'true');
|
itemCheckbox.setAttribute('checked', 'true');
|
||||||
}
|
}
|
||||||
itemCheckbox.addEventListener('change', hintChangeHandler);
|
itemCheckbox.addEventListener('change', updateListSetting);
|
||||||
itemLabel.appendChild(itemCheckbox);
|
itemLabel.appendChild(itemCheckbox);
|
||||||
|
|
||||||
const itemName = document.createElement('span');
|
const itemName = document.createElement('span');
|
||||||
itemName.innerText = item;
|
itemName.innerText = item;
|
||||||
itemLabel.appendChild(itemName);
|
itemLabel.appendChild(itemName);
|
||||||
|
|
||||||
itemDiv.appendChild(itemLabel);
|
itemRow.appendChild(itemLabel);
|
||||||
itemHintsDiv.appendChild(itemDiv);
|
itemHintsDiv.appendChild(itemRow);
|
||||||
});
|
});
|
||||||
|
|
||||||
itemHintsWrapper.appendChild(itemHintsDiv);
|
itemHintsWrapper.appendChild(itemHintsDiv);
|
||||||
itemHintsContainer.appendChild(itemHintsWrapper);
|
itemHintsContainer.appendChild(itemHintsWrapper);
|
||||||
|
|
||||||
|
// Starting Location Hints
|
||||||
const locationHintsWrapper = document.createElement('div');
|
const locationHintsWrapper = document.createElement('div');
|
||||||
locationHintsWrapper.classList.add('hints-wrapper');
|
locationHintsWrapper.classList.add('hints-wrapper');
|
||||||
locationHintsWrapper.innerText = 'Starting Location Hints';
|
locationHintsWrapper.innerText = 'Starting Location Hints';
|
||||||
|
|
||||||
const locationHintsDiv = document.createElement('div');
|
const locationHintsDiv = document.createElement('div');
|
||||||
locationHintsDiv.classList.add('item-container');
|
locationHintsDiv.classList.add('simple-list');
|
||||||
locations.forEach((location) => {
|
locations.forEach((location) => {
|
||||||
const locationDiv = document.createElement('div');
|
const locationRow = document.createElement('div');
|
||||||
locationDiv.classList.add('hint-div');
|
locationRow.classList.add('list-row');
|
||||||
|
|
||||||
const locationLabel = document.createElement('label');
|
const locationLabel = document.createElement('label');
|
||||||
locationLabel.setAttribute('for', `${game}-start_location_hints-${location}`);
|
locationLabel.setAttribute('for', `${game}-start_location_hints-${location}`);
|
||||||
|
@ -791,29 +894,89 @@ const buildHintsDiv = (game, items, locations) => {
|
||||||
if (currentSettings[game].start_location_hints.includes(location)) {
|
if (currentSettings[game].start_location_hints.includes(location)) {
|
||||||
locationCheckbox.setAttribute('checked', '1');
|
locationCheckbox.setAttribute('checked', '1');
|
||||||
}
|
}
|
||||||
locationCheckbox.addEventListener('change', hintChangeHandler);
|
locationCheckbox.addEventListener('change', updateListSetting);
|
||||||
locationLabel.appendChild(locationCheckbox);
|
locationLabel.appendChild(locationCheckbox);
|
||||||
|
|
||||||
const locationName = document.createElement('span');
|
const locationName = document.createElement('span');
|
||||||
locationName.innerText = location;
|
locationName.innerText = location;
|
||||||
locationLabel.appendChild(locationName);
|
locationLabel.appendChild(locationName);
|
||||||
|
|
||||||
locationDiv.appendChild(locationLabel);
|
locationRow.appendChild(locationLabel);
|
||||||
locationHintsDiv.appendChild(locationDiv);
|
locationHintsDiv.appendChild(locationRow);
|
||||||
});
|
});
|
||||||
|
|
||||||
locationHintsWrapper.appendChild(locationHintsDiv);
|
locationHintsWrapper.appendChild(locationHintsDiv);
|
||||||
itemHintsContainer.appendChild(locationHintsWrapper);
|
itemHintsContainer.appendChild(locationHintsWrapper);
|
||||||
|
|
||||||
|
hintsDiv.appendChild(itemHintsContainer);
|
||||||
|
return hintsDiv;
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildLocationsDiv = (game, locations) => {
|
||||||
|
const currentSettings = JSON.parse(localStorage.getItem('weighted-settings'));
|
||||||
|
locations.sort(); // Sort alphabetical, in-place
|
||||||
|
|
||||||
|
const locationsDiv = document.createElement('div');
|
||||||
|
locationsDiv.classList.add('locations-div');
|
||||||
|
const locationsHeader = document.createElement('h3');
|
||||||
|
locationsHeader.innerText = 'Priority & Exclusion Locations';
|
||||||
|
locationsDiv.appendChild(locationsHeader);
|
||||||
|
const locationsDescription = document.createElement('p');
|
||||||
|
locationsDescription.classList.add('setting-description');
|
||||||
|
locationsDescription.innerText = 'Priority locations guarantee a progression item will be placed there while ' +
|
||||||
|
'excluded locations will not contain progression or useful items.';
|
||||||
|
locationsDiv.appendChild(locationsDescription);
|
||||||
|
|
||||||
|
const locationsContainer = document.createElement('div');
|
||||||
|
locationsContainer.classList.add('locations-container');
|
||||||
|
|
||||||
|
// Priority Locations
|
||||||
|
const priorityLocationsWrapper = document.createElement('div');
|
||||||
|
priorityLocationsWrapper.classList.add('locations-wrapper');
|
||||||
|
priorityLocationsWrapper.innerText = 'Priority Locations';
|
||||||
|
|
||||||
|
const priorityLocationsDiv = document.createElement('div');
|
||||||
|
priorityLocationsDiv.classList.add('simple-list');
|
||||||
|
locations.forEach((location) => {
|
||||||
|
const locationRow = document.createElement('div');
|
||||||
|
locationRow.classList.add('list-row');
|
||||||
|
|
||||||
|
const locationLabel = document.createElement('label');
|
||||||
|
locationLabel.setAttribute('for', `${game}-priority_locations-${location}`);
|
||||||
|
|
||||||
|
const locationCheckbox = document.createElement('input');
|
||||||
|
locationCheckbox.setAttribute('type', 'checkbox');
|
||||||
|
locationCheckbox.setAttribute('id', `${game}-priority_locations-${location}`);
|
||||||
|
locationCheckbox.setAttribute('data-game', game);
|
||||||
|
locationCheckbox.setAttribute('data-setting', 'priority_locations');
|
||||||
|
locationCheckbox.setAttribute('data-option', location);
|
||||||
|
if (currentSettings[game].priority_locations.includes(location)) {
|
||||||
|
locationCheckbox.setAttribute('checked', '1');
|
||||||
|
}
|
||||||
|
locationCheckbox.addEventListener('change', updateListSetting);
|
||||||
|
locationLabel.appendChild(locationCheckbox);
|
||||||
|
|
||||||
|
const locationName = document.createElement('span');
|
||||||
|
locationName.innerText = location;
|
||||||
|
locationLabel.appendChild(locationName);
|
||||||
|
|
||||||
|
locationRow.appendChild(locationLabel);
|
||||||
|
priorityLocationsDiv.appendChild(locationRow);
|
||||||
|
});
|
||||||
|
|
||||||
|
priorityLocationsWrapper.appendChild(priorityLocationsDiv);
|
||||||
|
locationsContainer.appendChild(priorityLocationsWrapper);
|
||||||
|
|
||||||
|
// Exclude Locations
|
||||||
const excludeLocationsWrapper = document.createElement('div');
|
const excludeLocationsWrapper = document.createElement('div');
|
||||||
excludeLocationsWrapper.classList.add('hints-wrapper');
|
excludeLocationsWrapper.classList.add('locations-wrapper');
|
||||||
excludeLocationsWrapper.innerText = 'Exclude Locations';
|
excludeLocationsWrapper.innerText = 'Exclude Locations';
|
||||||
|
|
||||||
const excludeLocationsDiv = document.createElement('div');
|
const excludeLocationsDiv = document.createElement('div');
|
||||||
excludeLocationsDiv.classList.add('item-container');
|
excludeLocationsDiv.classList.add('simple-list');
|
||||||
locations.forEach((location) => {
|
locations.forEach((location) => {
|
||||||
const locationDiv = document.createElement('div');
|
const locationRow = document.createElement('div');
|
||||||
locationDiv.classList.add('hint-div');
|
locationRow.classList.add('list-row');
|
||||||
|
|
||||||
const locationLabel = document.createElement('label');
|
const locationLabel = document.createElement('label');
|
||||||
locationLabel.setAttribute('for', `${game}-exclude_locations-${location}`);
|
locationLabel.setAttribute('for', `${game}-exclude_locations-${location}`);
|
||||||
|
@ -827,40 +990,22 @@ const buildHintsDiv = (game, items, locations) => {
|
||||||
if (currentSettings[game].exclude_locations.includes(location)) {
|
if (currentSettings[game].exclude_locations.includes(location)) {
|
||||||
locationCheckbox.setAttribute('checked', '1');
|
locationCheckbox.setAttribute('checked', '1');
|
||||||
}
|
}
|
||||||
locationCheckbox.addEventListener('change', hintChangeHandler);
|
locationCheckbox.addEventListener('change', updateListSetting);
|
||||||
locationLabel.appendChild(locationCheckbox);
|
locationLabel.appendChild(locationCheckbox);
|
||||||
|
|
||||||
const locationName = document.createElement('span');
|
const locationName = document.createElement('span');
|
||||||
locationName.innerText = location;
|
locationName.innerText = location;
|
||||||
locationLabel.appendChild(locationName);
|
locationLabel.appendChild(locationName);
|
||||||
|
|
||||||
locationDiv.appendChild(locationLabel);
|
locationRow.appendChild(locationLabel);
|
||||||
excludeLocationsDiv.appendChild(locationDiv);
|
excludeLocationsDiv.appendChild(locationRow);
|
||||||
});
|
});
|
||||||
|
|
||||||
excludeLocationsWrapper.appendChild(excludeLocationsDiv);
|
excludeLocationsWrapper.appendChild(excludeLocationsDiv);
|
||||||
itemHintsContainer.appendChild(excludeLocationsWrapper);
|
locationsContainer.appendChild(excludeLocationsWrapper);
|
||||||
|
|
||||||
hintsDiv.appendChild(itemHintsContainer);
|
locationsDiv.appendChild(locationsContainer);
|
||||||
return hintsDiv;
|
return locationsDiv;
|
||||||
};
|
|
||||||
|
|
||||||
const hintChangeHandler = (evt) => {
|
|
||||||
const currentSettings = JSON.parse(localStorage.getItem('weighted-settings'));
|
|
||||||
const game = evt.target.getAttribute('data-game');
|
|
||||||
const setting = evt.target.getAttribute('data-setting');
|
|
||||||
const option = evt.target.getAttribute('data-option');
|
|
||||||
|
|
||||||
if (evt.target.checked) {
|
|
||||||
if (!currentSettings[game][setting].includes(option)) {
|
|
||||||
currentSettings[game][setting].push(option);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (currentSettings[game][setting].includes(option)) {
|
|
||||||
currentSettings[game][setting].splice(currentSettings[game][setting].indexOf(option), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
localStorage.setItem('weighted-settings', JSON.stringify(currentSettings));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateVisibleGames = () => {
|
const updateVisibleGames = () => {
|
||||||
|
@ -906,13 +1051,12 @@ const updateBaseSetting = (event) => {
|
||||||
localStorage.setItem('weighted-settings', JSON.stringify(settings));
|
localStorage.setItem('weighted-settings', JSON.stringify(settings));
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateGameSetting = (evt) => {
|
const updateRangeSetting = (evt) => {
|
||||||
const options = JSON.parse(localStorage.getItem('weighted-settings'));
|
const options = JSON.parse(localStorage.getItem('weighted-settings'));
|
||||||
const game = evt.target.getAttribute('data-game');
|
const game = evt.target.getAttribute('data-game');
|
||||||
const setting = evt.target.getAttribute('data-setting');
|
const setting = evt.target.getAttribute('data-setting');
|
||||||
const option = evt.target.getAttribute('data-option');
|
const option = evt.target.getAttribute('data-option');
|
||||||
document.getElementById(`${game}-${setting}-${option}`).innerText = evt.target.value;
|
document.getElementById(`${game}-${setting}-${option}`).innerText = evt.target.value;
|
||||||
console.log(event);
|
|
||||||
if (evt.action && evt.action === 'rangeDelete') {
|
if (evt.action && evt.action === 'rangeDelete') {
|
||||||
delete options[game][setting][option];
|
delete options[game][setting][option];
|
||||||
} else {
|
} else {
|
||||||
|
@ -921,6 +1065,26 @@ const updateGameSetting = (evt) => {
|
||||||
localStorage.setItem('weighted-settings', JSON.stringify(options));
|
localStorage.setItem('weighted-settings', JSON.stringify(options));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateListSetting = (evt) => {
|
||||||
|
const options = JSON.parse(localStorage.getItem('weighted-settings'));
|
||||||
|
const game = evt.target.getAttribute('data-game');
|
||||||
|
const setting = evt.target.getAttribute('data-setting');
|
||||||
|
const option = evt.target.getAttribute('data-option');
|
||||||
|
|
||||||
|
if (evt.target.checked) {
|
||||||
|
// If the option is to be enabled and it is already enabled, do nothing
|
||||||
|
if (options[game][setting].includes(option)) { return; }
|
||||||
|
|
||||||
|
options[game][setting].push(option);
|
||||||
|
} else {
|
||||||
|
// If the option is to be disabled and it is already disabled, do nothing
|
||||||
|
if (!options[game][setting].includes(option)) { return; }
|
||||||
|
|
||||||
|
options[game][setting].splice(options[game][setting].indexOf(option), 1);
|
||||||
|
}
|
||||||
|
localStorage.setItem('weighted-settings', JSON.stringify(options));
|
||||||
|
};
|
||||||
|
|
||||||
const updateItemSetting = (evt) => {
|
const updateItemSetting = (evt) => {
|
||||||
const options = JSON.parse(localStorage.getItem('weighted-settings'));
|
const options = JSON.parse(localStorage.getItem('weighted-settings'));
|
||||||
const game = evt.target.getAttribute('data-game');
|
const game = evt.target.getAttribute('data-game');
|
||||||
|
|
|
@ -157,41 +157,29 @@ html{
|
||||||
background-color: rgba(0, 0, 0, 0.1);
|
background-color: rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#weighted-settings .hints-div{
|
#weighted-settings .hints-div, #weighted-settings .locations-div{
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#weighted-settings .hints-div h3{
|
#weighted-settings .hints-div h3, #weighted-settings .locations-div h3{
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#weighted-settings .hints-div .hints-container{
|
#weighted-settings .hints-container, #weighted-settings .locations-container{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
#weighted-settings .hints-wrapper, #weighted-settings .locations-wrapper{
|
||||||
|
width: calc(50% - 0.5rem);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
#weighted-settings .hints-div .hints-wrapper{
|
#weighted-settings .hints-wrapper .simple-list, #weighted-settings .locations-wrapper .simple-list{
|
||||||
width: 32.5%;
|
margin-top: 0.25rem;
|
||||||
}
|
height: 300px;
|
||||||
|
font-weight: normal;
|
||||||
#weighted-settings .hints-div .hints-wrapper .hint-div{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#weighted-settings .hints-div .hints-wrapper .hint-div:hover{
|
|
||||||
background-color: rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#weighted-settings .hints-div .hints-wrapper .hint-div label{
|
|
||||||
flex-grow: 1;
|
|
||||||
padding: 0.125rem 0.5rem;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#weighted-settings #weighted-settings-button-row{
|
#weighted-settings #weighted-settings-button-row{
|
||||||
|
@ -280,6 +268,30 @@ html{
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#weighted-settings .simple-list{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
border: 1px solid #ffffff;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#weighted-settings .simple-list .list-row label{
|
||||||
|
display: block;
|
||||||
|
width: calc(100% - 0.5rem);
|
||||||
|
padding: 0.0625rem 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#weighted-settings .simple-list .list-row label:hover{
|
||||||
|
background-color: rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#weighted-settings .simple-list .list-row label input[type=checkbox]{
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
#weighted-settings .invisible{
|
#weighted-settings .invisible{
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue