Created
January 4, 2021 00:39
-
-
Save oliverbooth/3ef1c9a5c7a92fa588d2584b1fc16279 to your computer and use it in GitHub Desktop.
QoL Enhancements for https://phasmophobiatracker.site/
This file contains hidden or 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 Phasmophobia Evidence Tracker Enhanced | |
// @version 1 | |
// @namespace https://phasmophobiatracker.site/ | |
// @run-at document-start | |
// ==/UserScript== | |
const addJQuery = function(callback) { | |
const script = document.createElement('script'); | |
script.setAttribute('src', '//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js'); | |
script.addEventListener('load', function() { | |
const script = document.createElement('script'); | |
script.textContent = 'window.jQ=jQuery.noConflict(true);(' + callback.toString() + ')();'; | |
document.body.appendChild(script); | |
}); | |
document.body.appendChild(script); | |
} | |
const run = function() { | |
const sanitizeClassName = function(name) { | |
return name.toLowerCase().replace(' ', '-'); | |
} | |
class Evidence { | |
constructor(name, klass) { | |
this._name = name; | |
this._class = klass || sanitizeClassName(name); | |
} | |
class() { | |
return this._class; | |
} | |
name() { | |
return this._name; | |
} | |
}; | |
const Evidences = { | |
SpiritBox: new Evidence("Spirit Box"), | |
Fingerprints: new Evidence("Fingerprints"), | |
GhostWriting: new Evidence("Ghost Writing"), | |
FreezingTemperatures: new Evidence("Freezing Temperatures", "freezing-temp"), | |
EMF5: new Evidence("EMF 5", "emf"), | |
GhostOrbs: new Evidence("Ghost Orbs") | |
}; | |
const matchEvidence = function(name) { | |
for (let evidence of Object.values(Evidences)) { | |
if (evidence.class() == name) { | |
return evidence; | |
} | |
} | |
return null; | |
}; | |
class Ghost { | |
constructor(name, evidence) { | |
this._name = name; | |
this._class = sanitizeClassName(name); | |
this._evidence = evidence; | |
} | |
class() { | |
return this._class; | |
} | |
evidence() { | |
return this._evidence; | |
} | |
name() { | |
return this._name; | |
} | |
hasEvidence(evidence) { | |
if (!(evidence instanceof Evidence)) { | |
return false; | |
} | |
for (const e of this._evidence) { | |
if (evidence.class() == e.class()) { | |
return true; | |
} | |
} | |
return false; | |
} | |
}; | |
const Ghosts = { | |
Spirit: new Ghost("Spirit", [ Evidences.SpiritBox, Evidences.Fingerprints, Evidences.GhostWriting ]), | |
Wraith: new Ghost("Wraith", [ Evidences.SpiritBox, Evidences.Fingerprints, Evidences.FreezingTemperatures ]), | |
Phantom: new Ghost("Phantom", [ Evidences.FreezingTemperatures, Evidences.EMF5, Evidences.GhostOrbs ]), | |
Poltergeist: new Ghost("Poltergeist", [ Evidences.SpiritBox, Evidences.Fingerprints, Evidences.GhostOrbs ]), | |
Banshee: new Ghost("Banshee", [ Evidences.Fingerprints, Evidences.FreezingTemperatures, Evidences.EMF5 ]), | |
Jinn: new Ghost("Jinn", [ Evidences.SpiritBox, Evidences.EMF5, Evidences.GhostOrbs ]), | |
Mare: new Ghost("Mare", [ Evidences.SpiritBox, Evidences.FreezingTemperatures, Evidences.GhostOrbs ]), | |
Revenant: new Ghost("Revenant", [ Evidences.Fingerprints, Evidences.GhostWriting, Evidences.EMF5 ]), | |
Shade: new Ghost("Shade", [ Evidences.GhostWriting, Evidences.EMF5, Evidences.GhostOrbs ]), | |
Demon: new Ghost("Demon", [ Evidences.SpiritBox, Evidences.GhostWriting, Evidences.FreezingTemperatures ] ), | |
Yurei: new Ghost("Yurei", [ Evidences.GhostWriting, Evidences.FreezingTemperatures, Evidences.GhostOrbs ]), | |
Oni: new Ghost("Oni", [ Evidences.SpiritBox, Evidences.GhostWriting, Evidences.EMF5 ]) | |
}; | |
const includeGhost = function(ghost) { | |
const DOM = document.querySelector(`#row-${ghost.class()}`); | |
DOM.style.backgroundColor = ''; | |
DOM.classList.add('row-active'); | |
}; | |
const excludeGhost = function(ghost, highlight) { | |
const DOM = document.querySelector(`#row-${ghost.class()}`); | |
if (highlight === true) { | |
DOM.style.backgroundColor = '#f44336'; | |
} else { | |
DOM.style.backgroundColor = ''; | |
} | |
DOM.classList.remove('row-active'); | |
}; | |
const resetGhost = function(ghost) { | |
const DOM = document.querySelector(`#row-${ghost.class()}`); | |
DOM.style.backgroundColor = ''; | |
DOM.classList.remove('row-active'); | |
}; | |
const extendGhostTable = function() { | |
const table = document.getElementById('evidence-table'); | |
const tr = table.getElementsByTagName('tr')[0]; | |
const th = tr.getElementsByTagName('th')[0]; | |
th.colSpan = 1; | |
tr.insertCell(1).innerText = '✅'; | |
tr.insertCell(2).innerText = '❌'; | |
const tbody = table.getElementsByTagName('tbody')[0]; | |
for (let tr of tbody.children) { | |
const td = tr.getElementsByTagName("td"); | |
if (td.length == 2) { | |
const rowEvidence = tr.getElementsByTagName('input')[0].value; | |
tr.children[1].innerHTML = `<input class="include-evidence" type="checkbox" name="check-${rowEvidence}" id="check-${rowEvidence}" value="${rowEvidence}">` | |
tr.insertCell(2).innerHTML = `<input class="exclude-evidence" type="checkbox" name="check-ex-${rowEvidence}" id="check-ex-${rowEvidence}" value="${rowEvidence}">` | |
} else { | |
td[0].colSpan = 3; | |
} | |
} | |
}; | |
const getIncludedEvidence = function () { | |
const checkedEvidence = []; | |
jQ('.include-evidence:checked').each(function() { | |
checkedEvidence.push(matchEvidence(jQ(this).val())); | |
}); | |
return checkedEvidence; | |
}; | |
const getExcludedEvidence = function () { | |
const checkedEvidence = []; | |
jQ('.exclude-evidence:checked').each(function() { | |
checkedEvidence.push(matchEvidence(jQ(this).val())); | |
}); | |
return checkedEvidence; | |
}; | |
const updateGhostTable = function() { | |
const included = getIncludedEvidence(); | |
const excluded = getExcludedEvidence(); | |
const ghosts = Object.values(Ghosts); | |
let possibleGhosts = []; | |
const impossibleGhosts = []; | |
for (const ghost of ghosts) { | |
resetGhost(ghost); | |
let hasAllEvidence = included.length > 0; | |
for (const evidence of included) { | |
if (!ghost.hasEvidence(evidence)) { | |
hasAllEvidence = false; | |
} | |
} | |
if (hasAllEvidence) { | |
possibleGhosts.push(ghost); | |
} | |
} | |
for (const ghost of possibleGhosts) { | |
includeGhost(ghost); | |
} | |
if (excluded.length) { | |
for (const ghost of ghosts) { | |
for (const evidence of excluded) { | |
if (ghost.hasEvidence(evidence)) { | |
impossibleGhosts.push(ghost); | |
break; | |
} | |
} | |
} | |
possibleGhosts = possibleGhosts.filter(g => impossibleGhosts.includes(g)); | |
for (const ghost of possibleGhosts) { | |
includeGhost(ghost); | |
} | |
for (const ghost of impossibleGhosts) { | |
excludeGhost(ghost, possibleGhosts.length == 0); | |
} | |
} | |
}; | |
const resetEvents = function() { | |
jQ('input[type="checkbox"]').on('click', () => { | |
const el = jQ(this); | |
if (el.prop(':checked')) { | |
if (el.class().includes('include-')) { | |
jQ(`#check-ex-${el.val()}`).prop('checked', false); | |
} else { | |
jQ(`#check-${el.val()}`).prop('checked', true); | |
} | |
} | |
updateGhostTable(); | |
}); | |
}; | |
extendGhostTable(); | |
resetEvents(); | |
}; | |
window.addEventListener('load', () => addJQuery(run), false); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment