您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Script for storing and changing into outfits.
// ==UserScript== // @name Fallen London - Dressing Room - Chrome // @namespace fallenlondon/dressingroom // @description Script for storing and changing into outfits. // @author Travers // @include http://*fallenlondon.com/Gap/Load* // @include http://fallenlondon.storynexus.com/Gap/Load* // @version 1.41 // @grant none // ==/UserScript== var DB_NAME = 'Dressing Room for '; var DB_STORE_NAME = 'outfits'; var DB_VERSION = 1; var DEBUG = false; var outfitMode = {add: 1, change: 2, changing: 3} var db = null; var onMeTab = false; var itemsOwned = Object.create(null); var outfit; var record; setUpObservers(); function debugLog(msg) { if (DEBUG) { console.log('Fallen London - Dressing Room: ', msg); } } function debugDir(obj) { if (DEBUG) { console.dir(obj); } } function setUpObservers() { var target = document.querySelector('#meTab'); var peeper = new MutationObserver(checkMeOut); peeper.observe(target, {attributes: true, childList: false, characterData: false}); target = document.querySelector('#mainContentLoading'); peeper = new MutationObserver(checkOutMyLoad); peeper.observe(target, {attributes: true, childList: false, characterData: false}); } function checkMeOut(mutants, observer) { onMeTab = mutants[0].target.getAttribute(mutants[0].attributeName) == 'selected'; if (!db) { openDatabase(); } } function openDatabase() { var username = document.getElementsByClassName('subscription-username')[0].innerHTML; if (username.length < 1) { debugLog('openDatabase - username error'); return; } DB_NAME += username; var req = window.indexedDB.open(DB_NAME, DB_VERSION); req.onsuccess = function(evt) { db = this.result; db.onerror = function(evt) { console.error('Fallen London Dressing Room - DB - error: ', evt.target.errorCode); } debugLog('openDatabase - completed'); }; req.onerror = function(evt) { console.error('Fallen London Dressing Room - openDatabase - error: ', evt.target.errorCode); }; req.onupgradeneeded = function(evt) { debugLog('openDatabase - setting up database store'); var store = evt.currentTarget.result.createObjectStore(DB_STORE_NAME, {keyPath: 'Name'}); }; } function checkOutMyLoad(mutants, observer) { if (onMeTab) { var DR = document.getElementById('dressing-room'); if (DR == null) { var target = document.getElementsByClassName('redesign_heading')[0]; var newA = document.createElement('A'); newA.className = 'standard_btn label'; newA.style.position = 'absolute'; newA.style.right = '1em'; newA.style.top = '1em'; newA.innerHTML = 'DRESSING ROOM'; newA.addEventListener('click', function(){toggleVisibility('dressing-room');}); target.appendChild(newA); var newDiv = document.createElement('DIV'); newDiv.id = 'dressing-room'; newDiv.style.zIndex = '50'; newDiv.style.position = 'absolute'; newDiv.style.right = '1em'; newDiv.style.padding = '8px 12px'; newDiv.style.border = '3px solid #736448'; newDiv.style.color = '#000000'; newDiv.style.background = '#b8a98c none repeat scroll 0 0'; newDiv.style.boxShadow = '0 2px 8px #000000'; newDiv.style.fontSize = '15px'; newDiv.style.height = 'auto !important'; newDiv.style.width = 'auto !important'; newDiv.style.textTransform = 'none'; newDiv.style.visibility = 'hidden'; var newP = document.createElement('P'); var newText = document.createTextNode('What to wear? '); newP.style.fontWeight = 'bold'; newP.appendChild(newText); newP.appendChild(document.createElement('BR')); var newSelect = document.createElement('SELECT'); newSelect.id = 'outfit-name'; newSelect.style.fontWeight = 'bold'; newSelect.style.width = '15em'; newP.appendChild(newSelect); newText = document.createTextNode(' '); newP.appendChild(newText); var newButton = document.createElement('BUTTON'); newButton.style.backgroundColor = '#ffcc00'; newText = document.createTextNode('Change'); newButton.style.fontWeight = 'bold'; newButton.style.padding = '0px 5px'; newButton.style.border = '3px solid #ffee00'; newButton.appendChild(newText); newButton.addEventListener('click', function() { manageOutfit(outfitMode.change); }); newP.appendChild(newButton); newP.appendChild(document.createTextNode(' ')); var newButton = document.createElement('BUTTON'); newButton.style.backgroundColor = '#f440f6'; newText = document.createTextNode('Forget'); newButton.style.fontWeight = 'bold'; newButton.style.padding = '0px 5px'; newButton.style.border = '3px solid #ff50ff'; newButton.appendChild(newText); newButton.addEventListener('click', deleteOutfit); newP.appendChild(newButton); newDiv.appendChild(newP); newP = document.createElement('P'); newText = document.createTextNode('What am I wearing? '); newP.style.fontWeight = 'bold'; newP.appendChild(newText); newP.appendChild(document.createElement('BR')); var newInput = document.createElement('INPUT'); newInput.type = 'text'; newInput.id = 'new-outfit-name'; newInput.style.fontWeight = 'bold'; newInput.style.padding = '0px 5px'; newInput.style.width = '15em'; newP.appendChild(newInput); newText = document.createTextNode(' '); newP.appendChild(newText); newButton = document.createElement('BUTTON'); newButton.style.backgroundColor = '#ffcc00'; newText = document.createTextNode('Remember'); newButton.style.fontWeight = 'bold'; newButton.style.padding = '0px 5px'; newButton.style.border = '3px solid #ffee00'; newButton.appendChild(newText); newButton.addEventListener('click', function() { manageOutfit(outfitMode.add); }); newP.appendChild(newButton); newDiv.appendChild(newP); target.appendChild(newDiv); buildOptions(); target = document.getElementsByTagName('body')[0]; newDiv = document.createElement('DIV'); newDiv.id = 'dressing-room-changing-dialog'; newDiv.innerHTML = 'Donning my'; newDiv.style.zIndex = '100'; newDiv.style.position = 'absolute'; newDiv.style.margin = 'auto'; newDiv.style.top = '0'; newDiv.style.left = '0'; newDiv.style.bottom = '0'; newDiv.style.right = '0'; newDiv.style.width = '400px'; newDiv.style.height = '80px'; newDiv.style.lineHeight ='80px'; newDiv.style.textAlign = 'center'; newDiv.style.verticalAlign = 'middle'; newDiv.style.padding = '5px 5px'; newDiv.style.border = '3px solid #736448'; newDiv.style.color = '#000000'; newDiv.style.background = '#b8a98c none repeat scroll 0 0'; newDiv.style.boxShadow = '0 2px 8px #000000'; newDiv.style.fontSize = '20px'; newDiv.style.textTransform = 'none'; newDiv.style.visibility = 'hidden'; target.appendChild(newDiv); } } } function buildOptions() { if (db) { var store = db.transaction(DB_STORE_NAME).objectStore(DB_STORE_NAME); var optionsList = []; store.openCursor().onsuccess = function(evt) { var cursor = evt.target.result; if (cursor) { optionsList.push(cursor.value.Name); cursor.continue(); } else displayOptions(optionsList); } } } function displayOptions(optionsList) { var ONS = document.getElementById('outfit-name'); while (ONS.firstChild) { ONS.removeChild(ONS.firstChild); } var newOption = document.createElement('OPTION'); ONS.appendChild(newOption); optionsList.sort(function(a, b) { var nameA=a.toLowerCase(), nameB=b.toLowerCase(); if (nameA < nameB) return -1; if (nameA > nameB) return 1; return 0; }); for (var i = 0; i < optionsList.length; i++) { newOption = document.createElement('OPTION'); newOption.style.backgroundColor = (i % 2) ? '#cccccc' : '#aaaaaa'; newOption.innerHTML = optionsList[i]; ONS.appendChild(newOption); } } function toggleVisibility(elemID) { var element = document.getElementById(elemID); element.style.visibility = element.style.visibility == 'hidden' ? 'visible' : 'hidden'; } function addOutfit() { if (outfit.Name == '') { updateOutfit(); return; } var transaction = db.transaction([DB_STORE_NAME], 'readwrite'); var store = transaction.objectStore(DB_STORE_NAME); var req = store.add(outfit); req.onsuccess = function(evt) { debugLog('addOutfit - added'); }; buildOptions(); } function updateOutfit() { outfit.Name = document.getElementById('outfit-name').value; if (outfit.Name == '') { return; } var store = db.transaction([DB_STORE_NAME], 'readwrite').objectStore(DB_STORE_NAME); var req = store.get(outfit.Name); req.onsuccess = function(evt) { record = req.result; for (var attrName in outfit) { record[attrName] = outfit[attrName]; } var reqUpdate = store.put(record); reqUpdate.onsuccess = function(evt) { debugLog('updateOutfit - updated'); }; }; } function deleteOutfit() { var outfitName = document.getElementById('outfit-name').value; if (outfitName == '') { return; } var transaction = db.transaction([DB_STORE_NAME], 'readwrite'); var store = transaction.objectStore(DB_STORE_NAME); var req = store.delete(outfitName); req.onsuccess = function(evt) { debugLog('deleteOutfit - deleted'); }; buildOptions(); } function changeOutfit() { var outfitName = document.getElementById('outfit-name').value; var transaction = db.transaction([DB_STORE_NAME], 'readonly'); var store = transaction.objectStore(DB_STORE_NAME); var req = store.get(outfitName); req.onsuccess = function(evt) { record = req.result; debugLog('changeOutfit'); debugDir(record); var slots = ['Hat', 'Clothing', 'Gloves', 'Weapon', 'Boots', 'Companion', 'Affiliation', 'Transportation', 'HomeComfort']; for (var i = 0; i < slots.length; i++) { var slot = slots[i]; if (record[slot] != outfit[slot]) { if (record[slot] != '-' && record[slot] in itemsOwned) { adoptThing(record[slot], slot); } else if (outfit[slot] != '-') { unadoptThing(outfit[slot], slot); record[slot] = '-'; } } } setTimeout(function(){manageOutfit(outfitMode.changing);}, 1000); } } function changingOutfit() { var slots = ['Hat', 'Clothing', 'Gloves', 'Weapon', 'Boots', 'Companion', 'Affiliation', 'Transportation', 'HomeComfort']; for (var i = 0; i < slots.length; i++) { var slot = slots[i]; if (record[slot] != outfit[slot]) { setTimeout(function(){manageOutfit(outfitMode.changing);}, 1500); debugLog(slot + ' : ' + record[slot] + ' != ' + outfit[slot]); return; } } toggleVisibility('dressing-room-changing-dialog'); } function waitForElement(selector, time, mode) { if(document.querySelector(selector) != null) { manageOutfit2(mode, selector); } else { setTimeout(function() {waitForElement(selector, time, mode);}, time); } } function manageOutfit(mode) { if (mode == outfitMode.change) { var dlg = document.getElementById('dressing-room-changing-dialog'); var outfitName = document.getElementById('outfit-name').value; dlg.innerHTML = 'Donning <strong>' + outfitName + '</strong>'; toggleVisibility('dressing-room-changing-dialog'); } var expandedPage = document.getElementById('InvCat-Affiliation'); outfit = getCurrentItems(expandedPage); outfit.Name = document.getElementById('new-outfit-name').value; document.getElementById('new-outfit-name').value = ''; swapYouFrames(); if (expandedPage) { waitForElement('#InvCat-Hat', 1000, mode); } else { waitForElement('#InvCat-Affiliation', 1000, mode); } } function manageOutfit2(mode, selector) { var expandedPage = selector == '#InvCat-Affiliation' ? true : false; var outfit2 = getCurrentItems(expandedPage); for (var attrName in outfit2) { outfit[attrName] = outfit2[attrName]; } swapYouFrames(); if (mode == outfitMode.add) { addOutfit(); } else if (mode == outfitMode.change) { changeOutfit(); } else if (mode == outfitMode.changing) { changingOutfit(); } } function getCurrentItems(expandedPage) { if (expandedPage) { return { Affiliation: getItemNum('Affiliation'), Transportation: getItemNum('Transportation'), HomeComfort: getItemNum('HomeComfort') }; } return { Hat: getItemNum('Hat'), Clothing: getItemNum('Clothing'), Gloves: getItemNum('Gloves'), Weapon: getItemNum('Weapon'), Boots: getItemNum('Boots'), Companion: getItemNum('Companion') }; } function getItemNum(category) { var inventoryDiv = document.getElementById('InvCat-' + category); targetItemNum = '-'; if (inventoryDiv) { var aList = inventoryDiv.getElementsByTagName('A'); for (var j = 0; j < aList.length; j++) { if (aList[j].hasAttribute('onclick')) { var onClickEventString = aList[j].getAttribute('onclick'); if (onClickEventString.startsWith('unadoptThing') || onClickEventString.startsWith('adoptThing')) { var num = onClickEventString.slice(onClickEventString.indexOf('(') + 1, onClickEventString.indexOf(',')); if (!isNaN(Number(num))) { itemsOwned[num] = true; if (onClickEventString.startsWith('unadoptThing')) { targetItemNum = num; } } else { debugLog('Fallen London - Dressing Room: getItemNum - result was not a number: ' + num); } } } } } return targetItemNum; }