Chrome/Firefox MV3 extension that shows move type effectiveness during PokeRogue battles. Features: - Auto-detects battle state via Phaser game bridge (MAIN world) - Shows effectiveness multiplier, base power, and physical/special category - Supports single and double battles - Manual type calculator mode as fallback - Draggable overlay with dark theme matching PokeRogue aesthetic - Settings popup with position, opacity, and display options - Complete Gen 6+ type chart (18 types) from PokeRogue source data - Type colors matching PokeRogue's own color scheme
169 lines
5.7 KiB
JavaScript
169 lines
5.7 KiB
JavaScript
/**
|
|
* PokeRogue Type Effectiveness - Popup Script
|
|
* Handles settings UI and communicates with content script
|
|
*/
|
|
|
|
(function () {
|
|
'use strict';
|
|
|
|
const storage = (typeof browser !== 'undefined' && browser.storage)
|
|
? browser.storage
|
|
: chrome.storage;
|
|
const tabs = (typeof browser !== 'undefined' && browser.tabs)
|
|
? browser.tabs
|
|
: chrome.tabs;
|
|
|
|
const DEFAULT_SETTINGS = {
|
|
enabled: true,
|
|
position: 'top-right',
|
|
opacity: 90,
|
|
showPower: true,
|
|
showCategory: true,
|
|
showMoveNames: true,
|
|
compactMode: false,
|
|
manualMode: false,
|
|
manualEnemyTypes: []
|
|
};
|
|
|
|
// DOM elements
|
|
const enableToggle = document.getElementById('enableToggle');
|
|
const manualMode = document.getElementById('manualMode');
|
|
const opacitySlider = document.getElementById('opacitySlider');
|
|
const opacityValue = document.getElementById('opacityValue');
|
|
const showMoveNames = document.getElementById('showMoveNames');
|
|
const showPower = document.getElementById('showPower');
|
|
const showCategory = document.getElementById('showCategory');
|
|
const compactMode = document.getElementById('compactMode');
|
|
const refreshBtn = document.getElementById('refreshBtn');
|
|
const statusText = document.getElementById('statusText');
|
|
const posButtons = document.querySelectorAll('.pos-btn');
|
|
|
|
let currentSettings = { ...DEFAULT_SETTINGS };
|
|
|
|
// ─── Load Settings ─────────────────────────────────────────────
|
|
|
|
function loadSettings() {
|
|
storage.local.get(['settings'], (result) => {
|
|
currentSettings = { ...DEFAULT_SETTINGS, ...result.settings };
|
|
applyToUI(currentSettings);
|
|
});
|
|
}
|
|
|
|
function applyToUI(s) {
|
|
enableToggle.checked = s.enabled;
|
|
manualMode.checked = s.manualMode;
|
|
opacitySlider.value = s.opacity;
|
|
opacityValue.textContent = s.opacity + '%';
|
|
showMoveNames.checked = s.showMoveNames;
|
|
showPower.checked = s.showPower;
|
|
showCategory.checked = s.showCategory;
|
|
compactMode.checked = s.compactMode;
|
|
|
|
posButtons.forEach(btn => {
|
|
btn.classList.toggle('active', btn.dataset.pos === s.position);
|
|
});
|
|
}
|
|
|
|
// ─── Save Settings ─────────────────────────────────────────────
|
|
|
|
function saveSettings() {
|
|
currentSettings = {
|
|
...currentSettings,
|
|
enabled: enableToggle.checked,
|
|
manualMode: manualMode.checked,
|
|
opacity: parseInt(opacitySlider.value),
|
|
showMoveNames: showMoveNames.checked,
|
|
showPower: showPower.checked,
|
|
showCategory: showCategory.checked,
|
|
compactMode: compactMode.checked
|
|
};
|
|
|
|
storage.local.set({ settings: currentSettings });
|
|
}
|
|
|
|
// ─── Event Listeners ───────────────────────────────────────────
|
|
|
|
enableToggle.addEventListener('change', saveSettings);
|
|
manualMode.addEventListener('change', saveSettings);
|
|
showMoveNames.addEventListener('change', saveSettings);
|
|
showPower.addEventListener('change', saveSettings);
|
|
showCategory.addEventListener('change', saveSettings);
|
|
compactMode.addEventListener('change', saveSettings);
|
|
|
|
opacitySlider.addEventListener('input', () => {
|
|
opacityValue.textContent = opacitySlider.value + '%';
|
|
saveSettings();
|
|
});
|
|
|
|
posButtons.forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
posButtons.forEach(b => b.classList.remove('active'));
|
|
btn.classList.add('active');
|
|
currentSettings.position = btn.dataset.pos;
|
|
saveSettings();
|
|
|
|
// Reset overlay position so it re-applies the new corner
|
|
sendToContentScript({
|
|
type: 'UPDATE_SETTINGS',
|
|
settings: { ...currentSettings, _resetPosition: true }
|
|
});
|
|
});
|
|
});
|
|
|
|
refreshBtn.addEventListener('click', () => {
|
|
sendToContentScript({ type: 'REQUEST_REFRESH' });
|
|
refreshBtn.textContent = 'Refreshed!';
|
|
setTimeout(() => {
|
|
refreshBtn.textContent = 'Refresh';
|
|
}, 800);
|
|
});
|
|
|
|
// ─── Communication ─────────────────────────────────────────────
|
|
|
|
function sendToContentScript(message) {
|
|
tabs.query({ active: true, currentWindow: true }, (tabList) => {
|
|
if (tabList && tabList[0]) {
|
|
const sendMsg = (typeof browser !== 'undefined' && browser.tabs)
|
|
? browser.tabs.sendMessage
|
|
: chrome.tabs.sendMessage;
|
|
sendMsg(tabList[0].id, message, () => {
|
|
// Ignore errors (content script may not be loaded)
|
|
if (chrome.runtime.lastError) { /* intentional */ }
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
function getStatus() {
|
|
tabs.query({ active: true, currentWindow: true }, (tabList) => {
|
|
if (!tabList || !tabList[0]) {
|
|
statusText.textContent = 'No active tab';
|
|
return;
|
|
}
|
|
|
|
const url = tabList[0].url || '';
|
|
if (!url.includes('pokerogue.net')) {
|
|
statusText.textContent = 'Navigate to pokerogue.net';
|
|
return;
|
|
}
|
|
|
|
const sendMsg = (typeof browser !== 'undefined' && browser.tabs)
|
|
? browser.tabs.sendMessage
|
|
: chrome.tabs.sendMessage;
|
|
sendMsg(tabList[0].id, { type: 'GET_STATUS' }, (response) => {
|
|
if (chrome.runtime.lastError || !response) {
|
|
statusText.textContent = 'Extension loading...';
|
|
return;
|
|
}
|
|
statusText.textContent = response.status || 'Connected';
|
|
});
|
|
});
|
|
}
|
|
|
|
// ─── Init ──────────────────────────────────────────────────────
|
|
|
|
loadSettings();
|
|
getStatus();
|
|
|
|
})();
|