| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  | let spriteData = null; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 23:45:23 -04:00
										 |  |  | window.addEventListener('load', () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |   const gameSettings = document.getElementById('weighted-settings'); | 
					
						
							| 
									
										
										
										
											2021-02-07 13:58:24 -05:00
										 |  |  |   Promise.all([fetchWeightedSettingsYaml(), fetchWeightedSettingsJson(), fetchSpriteData()]).then((results) => { | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |     // Load YAML into object
 | 
					
						
							|  |  |  |     const sourceData = jsyaml.safeLoad(results[0], { json: true }); | 
					
						
							| 
									
										
										
										
											2021-02-07 13:58:24 -05:00
										 |  |  |     const wsVersion = sourceData.ws_version; | 
					
						
							|  |  |  |     delete sourceData.ws_version; // Do not include the settings version number in the export
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Check if settings exist in localStorage. If no settings are present, this is a first load (or reset to default)
 | 
					
						
							|  |  |  |     // and the version number should be silently updated
 | 
					
						
							|  |  |  |     if (!localStorage.getItem('weightedSettings1')) { | 
					
						
							|  |  |  |       localStorage.setItem('wsVersion', wsVersion); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Update localStorage with three settings objects. Preserve original objects if present.
 | 
					
						
							|  |  |  |     for (let i=1; i<=3; i++) { | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |       const localSettings = JSON.parse(localStorage.getItem(`weightedSettings${i}`)); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |       const updatedObj = localSettings ? Object.assign(sourceData, localSettings) : sourceData; | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |       localStorage.setItem(`weightedSettings${i}`, JSON.stringify(updatedObj)); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Build the entire UI
 | 
					
						
							| 
									
										
										
										
											2020-12-06 10:55:58 -05:00
										 |  |  |     buildUI(JSON.parse(results[1]), JSON.parse(results[2])); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Populate the UI and add event listeners
 | 
					
						
							|  |  |  |     populateSettings(); | 
					
						
							|  |  |  |     document.getElementById('preset-number').addEventListener('change', populateSettings); | 
					
						
							|  |  |  |     gameSettings.addEventListener('change', handleOptionChange); | 
					
						
							|  |  |  |     gameSettings.addEventListener('keyup', handleOptionChange); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     document.getElementById('export-button').addEventListener('click', exportSettings); | 
					
						
							| 
									
										
										
										
											2020-10-16 19:33:42 -04:00
										 |  |  |     document.getElementById('reset-to-default').addEventListener('click', resetToDefaults); | 
					
						
							| 
									
										
										
										
											2020-12-03 01:55:06 -05:00
										 |  |  |     adjustHeaderWidth(); | 
					
						
							| 
									
										
										
										
											2021-02-07 13:58:24 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (localStorage.getItem('wsVersion') !== wsVersion) { | 
					
						
							|  |  |  |       const userWarning = document.getElementById('user-warning'); | 
					
						
							|  |  |  |       const messageSpan = document.createElement('span'); | 
					
						
							|  |  |  |       messageSpan.innerHTML = "A new version of the weighted settings file is available. Click here to update!" + | 
					
						
							|  |  |  |         "<br />Be aware this will also reset your presets, so you should export them now if you want to save them."; | 
					
						
							|  |  |  |       userWarning.appendChild(messageSpan); | 
					
						
							|  |  |  |       userWarning.style.display = 'block'; | 
					
						
							|  |  |  |       userWarning.addEventListener('click', resetToDefaults); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   }).catch((error) => { | 
					
						
							| 
									
										
										
										
											2020-12-06 10:55:58 -05:00
										 |  |  |     console.error(error); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |     gameSettings.innerHTML = `
 | 
					
						
							| 
									
										
										
										
											2020-08-25 20:51:11 -04:00
										 |  |  |             <h2>Something went wrong while loading your game settings page.</h2> | 
					
						
							|  |  |  |             <h2>${error}</h2> | 
					
						
							|  |  |  |             <h2><a href="${window.location.origin}">Click here to return to safety!</a></h2> | 
					
						
							|  |  |  |             `
 | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-12-04 03:40:46 -05:00
										 |  |  |   document.getElementById('generate-game').addEventListener('click', () => generateGame()); | 
					
						
							|  |  |  |   document.getElementById('generate-race').addEventListener('click', () => generateGame(true)); | 
					
						
							| 
									
										
										
										
											2020-08-14 23:45:23 -04:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2020-08-19 21:51:59 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 13:58:24 -05:00
										 |  |  | const fetchWeightedSettingsYaml = () => new Promise((resolve, reject) => { | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   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); | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |   ajax.open('GET', `${window.location.origin}/static/static/weightedSettings.yaml` ,true); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   ajax.send(); | 
					
						
							| 
									
										
										
										
											2020-08-25 20:51:11 -04:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 13:58:24 -05:00
										 |  |  | const fetchWeightedSettingsJson = () => new Promise((resolve, reject) => { | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   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); | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |   ajax.open('GET', `${window.location.origin}/static/static/weightedSettings.json`, true); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   ajax.send(); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const fetchSpriteData = () => new Promise((resolve, reject) => { | 
					
						
							|  |  |  |   const ajax = new XMLHttpRequest(); | 
					
						
							|  |  |  |   ajax.onreadystatechange = () => { | 
					
						
							|  |  |  |     if (ajax.readyState !== 4) { return; } | 
					
						
							|  |  |  |     if (ajax.status !== 200) { | 
					
						
							|  |  |  |       reject('Unable to fetch sprite data.'); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     resolve(ajax.responseText); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   ajax.open('GET', `${window.location.origin}/static/static/spriteData.json`, true); | 
					
						
							|  |  |  |   ajax.send(); | 
					
						
							| 
									
										
										
										
											2020-08-25 20:51:11 -04:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-19 21:51:59 -04:00
										 |  |  | const handleOptionChange = (event) => { | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   if(!event.target.matches('.setting')) { return; } | 
					
						
							|  |  |  |   const presetNumber = document.getElementById('preset-number').value; | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |   const settings = JSON.parse(localStorage.getItem(`weightedSettings${presetNumber}`)) | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   const settingString = event.target.getAttribute('data-setting'); | 
					
						
							|  |  |  |   document.getElementById(settingString).innerText = event.target.value; | 
					
						
							|  |  |  |   if(getSettingValue(settings, settingString) !== false){ | 
					
						
							|  |  |  |     const keys = settingString.split('.'); | 
					
						
							|  |  |  |     switch (keys.length) { | 
					
						
							|  |  |  |       case 1: | 
					
						
							|  |  |  |         settings[keys[0]] = isNaN(event.target.value) ? | 
					
						
							|  |  |  |           event.target.value : parseInt(event.target.value, 10); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       case 2: | 
					
						
							|  |  |  |         settings[keys[0]][keys[1]] = isNaN(event.target.value) ? | 
					
						
							|  |  |  |           event.target.value : parseInt(event.target.value, 10); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       case 3: | 
					
						
							|  |  |  |         settings[keys[0]][keys[1]][keys[2]] = isNaN(event.target.value) ? | 
					
						
							|  |  |  |           event.target.value : parseInt(event.target.value, 10); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       default: | 
					
						
							| 
									
										
										
										
											2020-08-19 21:51:59 -04:00
										 |  |  |         console.warn(`Unknown setting string received: ${settingString}`) | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2020-08-19 21:51:59 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Save the updated settings object bask to localStorage
 | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |     localStorage.setItem(`weightedSettings${presetNumber}`, JSON.stringify(settings)); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   }else{ | 
					
						
							|  |  |  |     console.warn(`Unknown setting string received: ${settingString}`) | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-19 21:51:59 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const populateSettings = () => { | 
					
						
							| 
									
										
										
										
											2021-02-05 18:55:53 -05:00
										 |  |  |   buildSpriteOptions(); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   const presetNumber = document.getElementById('preset-number').value; | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |   const settings = JSON.parse(localStorage.getItem(`weightedSettings${presetNumber}`)) | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   const settingsInputs = Array.from(document.querySelectorAll('.setting')); | 
					
						
							|  |  |  |   settingsInputs.forEach((input) => { | 
					
						
							|  |  |  |     const settingString = input.getAttribute('data-setting'); | 
					
						
							|  |  |  |     const settingValue = getSettingValue(settings, settingString); | 
					
						
							|  |  |  |     if(settingValue !== false){ | 
					
						
							|  |  |  |       input.value = settingValue; | 
					
						
							|  |  |  |       document.getElementById(settingString).innerText = settingValue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-08-19 21:51:59 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Returns the value of the settings object, or false if the settings object does not exist | 
					
						
							|  |  |  |  * @param settings | 
					
						
							|  |  |  |  * @param keyString | 
					
						
							|  |  |  |  * @returns {string} | bool | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const getSettingValue = (settings, keyString) => { | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   const keys = keyString.split('.'); | 
					
						
							|  |  |  |   let currentVal = settings; | 
					
						
							|  |  |  |   keys.forEach((key) => { | 
					
						
							|  |  |  |     if(typeof(key) === 'string' && currentVal.hasOwnProperty(key)){ | 
					
						
							|  |  |  |       currentVal = currentVal[key]; | 
					
						
							|  |  |  |     }else{ | 
					
						
							| 
									
										
										
										
											2020-09-25 23:57:16 -04:00
										 |  |  |       currentVal = false; | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   return currentVal; | 
					
						
							| 
									
										
										
										
											2020-08-19 21:51:59 -04:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2020-08-25 20:51:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-27 21:31:18 -04:00
										 |  |  | const exportSettings = () => { | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   const presetNumber = document.getElementById('preset-number').value; | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |   const settings = JSON.parse(localStorage.getItem(`weightedSettings${presetNumber}`)); | 
					
						
							| 
									
										
										
										
											2020-10-18 00:51:50 -04:00
										 |  |  |   const yamlText = jsyaml.safeDump(settings, { noCompatMode: true }).replaceAll(/'(\d+)':/g, (x, y) => `${y}:`); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   download(`${settings.description}.yaml`, yamlText); | 
					
						
							| 
									
										
										
										
											2020-08-27 21:31:18 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-16 19:33:42 -04:00
										 |  |  | const resetToDefaults = () => { | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |   [1, 2, 3].forEach((presetNumber) => localStorage.removeItem(`weightedSettings${presetNumber}`)); | 
					
						
							| 
									
										
										
										
											2020-10-16 19:33:42 -04:00
										 |  |  |   location.reload(); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-27 21:31:18 -04:00
										 |  |  | /** Create an anchor and trigger a download of a text file. */ | 
					
						
							|  |  |  | const download = (filename, text) => { | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   const downloadLink = document.createElement('a'); | 
					
						
							|  |  |  |   downloadLink.setAttribute('href','data:text/yaml;charset=utf-8,'+ encodeURIComponent(text)) | 
					
						
							|  |  |  |   downloadLink.setAttribute('download', filename); | 
					
						
							|  |  |  |   downloadLink.style.display = 'none'; | 
					
						
							|  |  |  |   document.body.appendChild(downloadLink); | 
					
						
							|  |  |  |   downloadLink.click(); | 
					
						
							|  |  |  |   document.body.removeChild(downloadLink); | 
					
						
							| 
									
										
										
										
											2020-08-27 21:31:18 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-06 10:55:58 -05:00
										 |  |  | const buildUI = (settings, spriteData) => { | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   const settingsWrapper = document.getElementById('settings-wrapper'); | 
					
						
							|  |  |  |   const settingTypes = { | 
					
						
							|  |  |  |     gameOptions: 'Game Options', | 
					
						
							|  |  |  |     romOptions: 'ROM Options', | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-27 21:31:18 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   Object.keys(settingTypes).forEach((settingTypeKey) => { | 
					
						
							| 
									
										
										
										
											2020-11-30 21:15:47 -05:00
										 |  |  |     const sectionHeader = document.createElement('h2'); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |     sectionHeader.innerText = settingTypes[settingTypeKey]; | 
					
						
							|  |  |  |     settingsWrapper.appendChild(sectionHeader); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Object.values(settings[settingTypeKey]).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.'); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2020-08-27 21:31:18 -04:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Build sprite options
 | 
					
						
							| 
									
										
										
										
											2020-11-30 21:15:47 -05:00
										 |  |  |   const spriteOptionsHeader = document.createElement('h2'); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   spriteOptionsHeader.innerText = 'Sprite Options'; | 
					
						
							|  |  |  |   settingsWrapper.appendChild(spriteOptionsHeader); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const spriteOptionsWrapper = document.createElement('div'); | 
					
						
							| 
									
										
										
										
											2021-02-05 18:55:53 -05:00
										 |  |  |   spriteOptionsWrapper.setAttribute('id', 'sprite-options-wrapper'); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   spriteOptionsWrapper.className = 'setting-wrapper'; | 
					
						
							| 
									
										
										
										
											2021-02-05 18:55:53 -05:00
										 |  |  |   settingsWrapper.appendChild(spriteOptionsWrapper); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Append sprite picker
 | 
					
						
							|  |  |  |   settingsWrapper.appendChild(buildSpritePicker(spriteData)); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const buildSpriteOptions = () => { | 
					
						
							|  |  |  |   const spriteOptionsWrapper = document.getElementById('sprite-options-wrapper'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Clear the contents of the wrapper div
 | 
					
						
							|  |  |  |   while(spriteOptionsWrapper.firstChild){ | 
					
						
							|  |  |  |     spriteOptionsWrapper.removeChild(spriteOptionsWrapper.lastChild); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const spriteOptionsTitle = document.createElement('span'); | 
					
						
							|  |  |  |   spriteOptionsTitle.className = 'title-span'; | 
					
						
							|  |  |  |   spriteOptionsTitle.innerText = 'Alternate Sprites'; | 
					
						
							|  |  |  |   spriteOptionsWrapper.appendChild(spriteOptionsTitle); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const spriteOptionsDescription = document.createElement('span'); | 
					
						
							|  |  |  |   spriteOptionsDescription.className = 'description-span'; | 
					
						
							| 
									
										
										
										
											2021-01-26 18:29:23 -05:00
										 |  |  |   spriteOptionsDescription.innerHTML = 'Choose an alternate sprite to play the game with. Additional randomization ' + | 
					
						
							|  |  |  |     'options are documented in the ' + | 
					
						
							|  |  |  |     '<a href="https://github.com/Berserker66/MultiWorld-Utilities/blob/main/playerSettings.yaml#L374">settings file</a>.'; | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   spriteOptionsWrapper.appendChild(spriteOptionsDescription); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const spriteOptionsTable = document.createElement('table'); | 
					
						
							|  |  |  |   spriteOptionsTable.setAttribute('id', 'sprite-options-table'); | 
					
						
							|  |  |  |   spriteOptionsTable.className = 'option-set'; | 
					
						
							|  |  |  |   const tbody = document.createElement('tbody'); | 
					
						
							|  |  |  |   tbody.setAttribute('id', 'sprites-tbody'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const currentPreset = document.getElementById('preset-number').value; | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |   const playerSettings = JSON.parse(localStorage.getItem(`weightedSettings${currentPreset}`)); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-16 19:33:42 -04:00
										 |  |  |   // Manually add a row for random sprites
 | 
					
						
							|  |  |  |   addSpriteRow(tbody, playerSettings, 'random'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   // Add a row for each sprite currently present in the player's settings
 | 
					
						
							|  |  |  |   Object.keys(playerSettings.rom.sprite).forEach((spriteName) => { | 
					
						
							| 
									
										
										
										
											2020-10-16 19:33:42 -04:00
										 |  |  |     if(['random'].indexOf(spriteName) > -1) return; | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |     addSpriteRow(tbody, playerSettings, spriteName) | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   spriteOptionsTable.appendChild(tbody); | 
					
						
							|  |  |  |   spriteOptionsWrapper.appendChild(spriteOptionsTable); | 
					
						
							| 
									
										
										
										
											2020-08-25 20:51:11 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const buildRangeSettings = (parentElement, settings) => { | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   // 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.'); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-25 20:51:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   const settingWrapper = document.createElement('div'); | 
					
						
							|  |  |  |   settingWrapper.className = 'setting-wrapper'; | 
					
						
							| 
									
										
										
										
											2020-08-25 20:51:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   if(typeof(settings.friendlyName) !== 'undefined' && settings.friendlyName){ | 
					
						
							|  |  |  |     const sectionTitle = document.createElement('span'); | 
					
						
							|  |  |  |     sectionTitle.className = 'title-span'; | 
					
						
							|  |  |  |     sectionTitle.innerText = settings.friendlyName; | 
					
						
							|  |  |  |     settingWrapper.appendChild(sectionTitle); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-25 20:51:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   if(settings.description){ | 
					
						
							|  |  |  |     const description = document.createElement('span'); | 
					
						
							|  |  |  |     description.className = 'description-span'; | 
					
						
							|  |  |  |     description.innerText = settings.description; | 
					
						
							|  |  |  |     settingWrapper.appendChild(description); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-25 20:51:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   // 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.setAttribute('data-tooltip', setting.description); | 
					
						
							|  |  |  |     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 addSpriteRow = (tbody, playerSettings, spriteName) => { | 
					
						
							|  |  |  |   const rowId = (Math.random() * 1000000).toString(); | 
					
						
							|  |  |  |   const optionId = (Math.random() * 1000000).toString(); | 
					
						
							|  |  |  |   const tr = document.createElement('tr'); | 
					
						
							|  |  |  |   tr.setAttribute('id', rowId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Option Name
 | 
					
						
							|  |  |  |   const optionName = document.createElement('td'); | 
					
						
							|  |  |  |   optionName.className = 'option-name'; | 
					
						
							|  |  |  |   const label = document.createElement('label'); | 
					
						
							|  |  |  |   label.htmlFor = optionId; | 
					
						
							|  |  |  |   label.innerText = spriteName; | 
					
						
							|  |  |  |   optionName.appendChild(label); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-16 19:33:42 -04:00
										 |  |  |   if(['random', 'random_sprite_on_event'].indexOf(spriteName) === -1) { | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |     const deleteButton = document.createElement('span'); | 
					
						
							|  |  |  |     deleteButton.setAttribute('data-sprite', spriteName); | 
					
						
							|  |  |  |     deleteButton.setAttribute('data-row-id', rowId); | 
					
						
							|  |  |  |     deleteButton.innerText = ' (❌)'; | 
					
						
							|  |  |  |     deleteButton.className = 'delete-button'; | 
					
						
							|  |  |  |     optionName.appendChild(deleteButton); | 
					
						
							|  |  |  |     deleteButton.addEventListener('click', removeSpriteOption); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tr.appendChild(optionName); | 
					
						
							| 
									
										
										
										
											2020-08-25 20:51:11 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   // Option Value
 | 
					
						
							|  |  |  |   const optionValue = document.createElement('td'); | 
					
						
							|  |  |  |   optionValue.className = 'option-value'; | 
					
						
							|  |  |  |   const input = document.createElement('input'); | 
					
						
							|  |  |  |   input.className = 'setting'; | 
					
						
							|  |  |  |   input.setAttribute('id', optionId); | 
					
						
							|  |  |  |   input.setAttribute('type', 'range'); | 
					
						
							|  |  |  |   input.setAttribute('min', '0'); | 
					
						
							|  |  |  |   input.setAttribute('max', '100'); | 
					
						
							|  |  |  |   input.setAttribute('data-setting', `rom.sprite.${spriteName}`); | 
					
						
							| 
									
										
										
										
											2020-09-05 19:10:48 -04:00
										 |  |  |   input.value = "50"; | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   optionValue.appendChild(input); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Value display
 | 
					
						
							|  |  |  |   const valueDisplay = document.createElement('span'); | 
					
						
							|  |  |  |   valueDisplay.setAttribute('id', `rom.sprite.${spriteName}`); | 
					
						
							|  |  |  |   valueDisplay.innerText = playerSettings.rom.sprite.hasOwnProperty(spriteName) ? | 
					
						
							|  |  |  |     playerSettings.rom.sprite[spriteName] : '0'; | 
					
						
							|  |  |  |   optionValue.appendChild(valueDisplay); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tr.appendChild(optionValue); | 
					
						
							|  |  |  |   tbody.appendChild(tr); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const addSpriteOption = (event) => { | 
					
						
							|  |  |  |   const presetNumber = document.getElementById('preset-number').value; | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |   const playerSettings = JSON.parse(localStorage.getItem(`weightedSettings${presetNumber}`)); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   const spriteName = event.target.getAttribute('data-sprite'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (Object.keys(playerSettings.rom.sprite).indexOf(spriteName) !== -1) { | 
					
						
							|  |  |  |     // Do not add the same sprite twice
 | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Add option to playerSettings object
 | 
					
						
							|  |  |  |   playerSettings.rom.sprite[event.target.getAttribute('data-sprite')] = 50; | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |   localStorage.setItem(`weightedSettings${presetNumber}`, JSON.stringify(playerSettings)); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Add <tr> to #sprite-options-table
 | 
					
						
							|  |  |  |   const tbody = document.getElementById('sprites-tbody'); | 
					
						
							|  |  |  |   addSpriteRow(tbody, playerSettings, spriteName); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const removeSpriteOption = (event) => { | 
					
						
							|  |  |  |   const presetNumber = document.getElementById('preset-number').value; | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |   const playerSettings = JSON.parse(localStorage.getItem(`weightedSettings${presetNumber}`)); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   const spriteName = event.target.getAttribute('data-sprite'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Remove option from playerSettings object
 | 
					
						
							|  |  |  |   delete playerSettings.rom.sprite[spriteName]; | 
					
						
							| 
									
										
										
										
											2020-12-03 18:27:32 -05:00
										 |  |  |   localStorage.setItem(`weightedSettings${presetNumber}`, JSON.stringify(playerSettings)); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Remove <tr> from #sprite-options-table
 | 
					
						
							|  |  |  |   const tr = document.getElementById(event.target.getAttribute('data-row-id')); | 
					
						
							|  |  |  |   tr.parentNode.removeChild(tr); | 
					
						
							| 
									
										
										
										
											2020-08-25 20:51:11 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-06 10:55:58 -05:00
										 |  |  | const buildSpritePicker = (spriteData) => { | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |   const spritePicker = document.createElement('div'); | 
					
						
							|  |  |  |   spritePicker.setAttribute('id', 'sprite-picker'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Build description
 | 
					
						
							|  |  |  |   const description = document.createElement('span'); | 
					
						
							|  |  |  |   description.innerText = 'To add a sprite to your playable list, click the one you want below.'; | 
					
						
							|  |  |  |   spritePicker.appendChild(description); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const sprites = document.createElement('div'); | 
					
						
							|  |  |  |   sprites.setAttribute('id', 'sprite-picker-sprites'); | 
					
						
							| 
									
										
										
										
											2020-12-06 10:55:58 -05:00
										 |  |  |   spriteData.sprites.forEach((sprite) => { | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |     const spriteImg = document.createElement('img'); | 
					
						
							| 
									
										
										
										
											2021-03-13 18:53:53 -05:00
										 |  |  |     let spriteGifFile = sprite.file.split('.'); | 
					
						
							|  |  |  |     spriteGifFile.pop(); | 
					
						
							|  |  |  |     spriteGifFile = spriteGifFile.join('.') + '.gif'; | 
					
						
							|  |  |  |     spriteImg.setAttribute('src', `static/static/sprites/${spriteGifFile}`); | 
					
						
							|  |  |  |     spriteImg.setAttribute('data-sprite', sprite.file.split('.')[0]); | 
					
						
							| 
									
										
										
										
											2020-12-06 10:55:58 -05:00
										 |  |  |     spriteImg.setAttribute('alt', sprite.name); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Wrap the image in a span to allow for tooltip presence
 | 
					
						
							|  |  |  |     const imgWrapper = document.createElement('span'); | 
					
						
							|  |  |  |     imgWrapper.className = 'sprite-img-wrapper'; | 
					
						
							| 
									
										
										
										
											2020-12-06 10:55:58 -05:00
										 |  |  |     imgWrapper.setAttribute('data-tooltip', `${sprite.name}${sprite.author ? `, by ${sprite.author}` : ''}`); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |     imgWrapper.appendChild(spriteImg); | 
					
						
							| 
									
										
										
										
											2020-12-06 10:55:58 -05:00
										 |  |  |     imgWrapper.setAttribute('data-sprite', sprite.name); | 
					
						
							| 
									
										
										
										
											2020-09-05 18:51:46 -04:00
										 |  |  |     sprites.appendChild(imgWrapper); | 
					
						
							|  |  |  |     imgWrapper.addEventListener('click', addSpriteOption); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   spritePicker.appendChild(sprites); | 
					
						
							|  |  |  |   return spritePicker; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2020-12-04 03:40:46 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | const generateGame = (raceMode = false) => { | 
					
						
							|  |  |  |   const presetNumber = document.getElementById('preset-number').value; | 
					
						
							|  |  |  |   axios.post('/api/generate', { | 
					
						
							|  |  |  |     weights: { player: localStorage.getItem(`weightedSettings${presetNumber}`) }, | 
					
						
							|  |  |  |     presetData: { player: localStorage.getItem(`weightedSettings${presetNumber}`) }, | 
					
						
							|  |  |  |     playerCount: 1, | 
					
						
							|  |  |  |     race: raceMode ? '1' : '0', | 
					
						
							|  |  |  |   }).then((response) => { | 
					
						
							|  |  |  |     window.location.href = response.data.url; | 
					
						
							| 
									
										
										
										
											2021-05-13 21:33:56 -04:00
										 |  |  |   }).catch((error) => { | 
					
						
							|  |  |  |     const userMessage = document.getElementById('user-message'); | 
					
						
							|  |  |  |     userMessage.innerText = 'Something went wrong and your game could not be generated.'; | 
					
						
							|  |  |  |     userMessage.classList.add('visible'); | 
					
						
							|  |  |  |     window.scrollTo(0, 0); | 
					
						
							|  |  |  |     console.error(error); | 
					
						
							| 
									
										
										
										
											2020-12-04 03:40:46 -05:00
										 |  |  |   }); | 
					
						
							|  |  |  | }; |