Last active
June 29, 2024 20:54
-
-
Save toriningen/e89bfb6dbb46fe86cbedde1c99cfbb75 to your computer and use it in GitHub Desktop.
A Better Dark Room (QoL userscript)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name A Better Dark Room | |
// @namespace http://tampermonkey.net/ | |
// @version 2024-06-29 | |
// @description quality of life improvements | |
// @author toriningen | |
// @match https://adarkroom.doublespeakgames.com/* | |
// @icon https://adarkroom.doublespeakgames.com/favicon.ico | |
// @grant none | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
function addStyle(css) { | |
const id = 'trng-style'; | |
const style = document.getElementById(id) || (() => { | |
const style = document.createElement('style'); | |
style.id = id; | |
style.type = 'text/css'; | |
document.head.appendChild(style); | |
return style; | |
})(); | |
const sheet = style.sheet; | |
sheet.insertRule(css.trim(), (sheet.rules || sheet.cssRules || []).length); | |
} | |
const trngButtonCls = 'trng-button'; | |
const trngWeaponCls = 'trng-weapon'; | |
function addButtonStyle() { | |
addStyle(` | |
.${trngButtonCls}::before { | |
content: ''; | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
pointer-events: none; | |
box-sizing: border-box; | |
} | |
`); | |
addStyle(` | |
.${trngButtonCls}::before { | |
background: rgba(0,255,0,0.3); | |
} | |
`); | |
addStyle(` | |
.disabled.${trngButtonCls}::before { | |
background: rgba(0,255,0,0.1); | |
} | |
`); | |
} | |
function addWeaponStyle() { | |
addStyle(` | |
.${trngWeaponCls}::before { | |
content: ''; | |
display: block; | |
position: absolute; | |
left: -1.1em; | |
top: -0.25em; | |
width: 100%; | |
height: calc(100% + 0.5em); | |
background: rgba(255,0,0,0.3); | |
pointer-events: none; | |
box-sizing: border-box; | |
} | |
`); | |
} | |
addWeaponStyle(); | |
addButtonStyle(); | |
const autoClickButtons = new Set(); | |
const selectedWeapons = new Set(["fists"]); | |
function makeCooldownObserver() { | |
return new MutationObserver( | |
(mutations) => { | |
for (const mutation of mutations) { | |
if (mutation.type !== 'attributes') { | |
continue; | |
} | |
if (mutation.attributeName !== 'class') { | |
continue; | |
} | |
const $target = $(mutation.target); | |
if ($target.hasClass('disabled')) { | |
continue; | |
} | |
$target.trigger('cooldown'); | |
} | |
} | |
); | |
} | |
const stateKey = 'trngSave'; | |
function saveState() { | |
} | |
function loadState() { | |
} | |
function isAutoClickButton(btn) { | |
return autoClickButtons.has(btn); | |
// return $(btn).hasClass(trngButtonCls); | |
} | |
function addAutoClickButton(btn) { | |
autoClickButtons.add(btn); | |
const $btn = $(btn); | |
const cooldownObserver = makeCooldownObserver(); | |
$btn.data('cooldownObserver', cooldownObserver); | |
$btn.on('cooldown', () => { | |
if (autoClickButtons.has(btn)) { | |
$btn.click(); | |
} | |
}); | |
$btn.addClass(trngButtonCls); | |
cooldownObserver.observe(btn, { attributes: true, attributeFilter: ['class'] }); | |
if (!$btn.hasClass('disabled')) { | |
$btn.click(); | |
} | |
saveState(); | |
} | |
function removeAutoClickButton(btn) { | |
autoClickButtons.delete(btn); | |
const $btn = $(btn); | |
const cooldownObserver = $btn.data('cooldownObserver'); | |
if (cooldownObserver != null) { | |
cooldownObserver.disconnect(); | |
} | |
$btn.removeClass(trngButtonCls); | |
saveState(); | |
} | |
function toggleWeapon(row) { | |
const $row = $(row); | |
const key = ($row.attr('key') || '').replace(/ /g, '-'); | |
if (!key) { | |
return; | |
} | |
const wasActive = $row.hasClass(trngWeaponCls); | |
if (wasActive) { | |
selectedWeapons.delete(key); | |
$row.removeClass(trngWeaponCls); | |
} else { | |
selectedWeapons.add(key); | |
$row.addClass(trngWeaponCls); | |
} | |
saveState(); | |
} | |
function waitForFight() { | |
function handleNode(node) { | |
for (const weapon of selectedWeapons) { | |
const sel = `#attack_${weapon}`; | |
const attackBtn = $(node).find(sel).addBack(sel).filter(sel)[0]; | |
if (attackBtn != null) { | |
addAutoClickButton(attackBtn); | |
} | |
} | |
} | |
const observer = new MutationObserver( | |
(mutations) => { | |
for (const mutation of mutations) { | |
if (mutation.type !== 'childList') { | |
continue; | |
} | |
for (const node of mutation.addedNodes) { | |
if (node.nodeType !== Node.ELEMENT_NODE) { | |
continue; | |
} | |
handleNode(node); | |
} | |
} | |
} | |
); | |
observer.observe(document, { subtree: true, childList: true }); | |
} | |
document.addEventListener('click', function(event) { | |
if (!event.altKey) { | |
return; | |
} | |
if (!event.target.matches('.button')) { | |
return; | |
} | |
event.stopImmediatePropagation(); | |
event.preventDefault(); | |
if (event.target.matches('.eventPanel .button')) { | |
// only top-level buttons supported | |
return; | |
} | |
const target = event.target; | |
const $target = $(target); | |
if (!isAutoClickButton(target)) { | |
addAutoClickButton(target); | |
} else { | |
removeAutoClickButton(target); | |
} | |
}, true); | |
$('#outfitting').on('click', '.outfitRow', (event) => { | |
if (!event.altKey) { | |
return; | |
} | |
event.stopImmediatePropagation(); | |
event.preventDefault(); | |
toggleWeapon(event.target); | |
}); | |
loadState(); | |
waitForFight(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment