MediaWiki:Common.js: Difference between revisions
Jump to navigation
Jump to search
Switched to mw.hook |
Switched to use CSS class for passing arguments |
||
| Line 12: | Line 12: | ||
calcContainer.dataset.initialized = 'true'; | calcContainer.dataset.initialized = 'true'; | ||
const | const skillClass = Array.from(calcContainer.classList).find(c => c.startsWith('skill-')); | ||
if (!skillClass) { | |||
calcContainer.innerHTML = "<p style='color:red;'>Error: No skill class found on container.</p>"; | |||
return; | |||
} | |||
const currentSkill = skillClass.replace('skill-', ''); // e.g., "Mining" | |||
// Raw XP Table (Level 1 to 99) | // Raw XP Table (Level 1 to 99) | ||
Latest revision as of 19:17, 18 July 2026
$(document).ready(function() {
$('#ca-nstab-main a').text('Article');
$('#ca-history a').text('History');
$('#ca-view a').text('Read');
});
// Skill Calculator logic to be embedded in MediaWiki:Common.js
mw.hook('wikipage.content').add(function($content) {
// Only run if the page contains a calculator container
const calcContainer = $content.find('#wiki-skill-calc')[0];
if (!calcContainer) return;
if (calcContainer.dataset.initialized) return;
calcContainer.dataset.initialized = 'true';
const skillClass = Array.from(calcContainer.classList).find(c => c.startsWith('skill-'));
if (!skillClass) {
calcContainer.innerHTML = "<p style='color:red;'>Error: No skill class found on container.</p>";
return;
}
const currentSkill = skillClass.replace('skill-', ''); // e.g., "Mining"
// Raw XP Table (Level 1 to 99)
const xpTable = [
0, 0, 74, 160, 258, 371, 500, 649, 820, 1016, 1241, 1500, 1797, 2139, 2531, 2982, 3500, 4095, 4778, 5563, 6464, 7500, 8690, 10056, 11626, 13429, 15500, 17879, 20612, 23751, 27358, 31500, 36258, 41724, 48003, 55215, 63500, 73017, 83949, 96506, 110930, 127500, 146533, 168397, 193512, 222361, 255500, 293567, 337294, 387523, 445222, 511500, 587634, 675088, 775547, 890944, 1023500, 1175767, 1350676, 1551594, 1782388, 2047500, 2352034, 2701852, 3103688, 3565275, 4095500, 4704568, 5404204, 6207875, 7131050, 8191500, 9409637, 10808909, 12416250, 14262600, 16383500, 18819774, 21618318, 24833000, 28525701, 32767500, 37640048, 43237135, 49666500, 57051902, 65535500, 75280595, 86474770, 99333501, 114104303, 131071500, 150561691, 172950041, 198667502, 228209107, 262143500, 301123982, 345900582, 397335504
];
// Data compiled from the scraped files
const skillData = {
"Mining": [
{ "name": "Copper Ore", "reqLevel": 1, "xp": 15 },
{ "name": "Tin Ore", "reqLevel": 1, "xp": 15 },
{ "name": "Iron Ore", "reqLevel": 10, "xp": 30 },
{ "name": "Coal Ore", "reqLevel": 20, "xp": 80 },
{ "name": "Mithril Ore", "reqLevel": 30, "xp": 150 },
{ "name": "Gold Ore", "reqLevel": 40, "xp": 350 },
{ "name": "Essence Geode", "reqLevel": 50, "xp": 550 }
],
"Fishing": [
{ "name": "Minnow", "reqLevel": 1, "xp": 8 },
{ "name": "Common Trout", "reqLevel": 5, "xp": 75 },
{ "name": "Perch", "reqLevel": 10, "xp": 225 },
{ "name": "Bass", "reqLevel": 20, "xp": 200 },
{ "name": "Blue Gill", "reqLevel": 30, "xp": 75 },
{ "name": "Elder Trout", "reqLevel": 40, "xp": 500 },
{ "name": "Carp", "reqLevel": 50, "xp": 1250 }
],
"PotionMaking": [
{ "name": "Weak Health Potion", "reqLevel": 1, "xp": 25 },
{ "name": "Health Potion", "reqLevel": 10, "xp": 100 },
{ "name": "Attack Potion", "reqLevel": 25, "xp": 1500 },
{ "name": "Fishing Potion", "reqLevel": 30, "xp": 2000 },
{ "name": "Mining Potion", "reqLevel": 30, "xp": 2000 },
{ "name": "Shield Potion", "reqLevel": 40, "xp": 3500 },
{ "name": "Strong Health Potion", "reqLevel": 50, "xp": 5000 },
{ "name": "Strong Shield Potion", "reqLevel": 60, "xp": 8000 }
]
};
const actions = skillData[currentSkill];
if (!actions) {
calcContainer.innerHTML = "<p style='color:red;'>Calculator data not found for " + currentSkill + ".</p>";
return;
}
// Convert level to XP
function levelToXP(level) {
if (level < 1) return xpTable[1];
if (level > 99) return xpTable[99];
return xpTable[level];
}
function calculateActions(currentXP, targetXP) {
const xpNeeded = targetXP - currentXP;
if (xpNeeded <= 0) return [];
return actions.map(action => {
const amount = Math.ceil(xpNeeded / action.xp);
return { ...action, amount, xpNeeded };
}).sort((a, b) => a.reqLevel - b.reqLevel);
}
function renderCalculator() {
const currentLvl = parseInt(document.getElementById('calc-current-lvl').value) || 1;
const targetLvl = parseInt(document.getElementById('calc-target-lvl').value) || (currentLvl + 1);
const currentXP = levelToXP(currentLvl);
const targetXP = levelToXP(targetLvl);
const xpNeeded = targetXP - currentXP;
let html = `
<div class="calc-results-header">
<h3>XP Required: <span>${xpNeeded.toLocaleString()}</span></h3>
<p>From Level ${currentLvl} (${currentXP.toLocaleString()} XP) to Level ${targetLvl} (${targetXP.toLocaleString()} XP)</p>
</div>
<table class="wikitable calc-table">
<tr><th>Action</th><th>Level Req.</th><th>XP/Action</th><th>Total Actions</th></tr>
`;
if (xpNeeded <= 0) {
html += `<tr><td colspan="4" style="text-align:center;">You have already reached the target level!</td></tr>`;
} else {
const results = calculateActions(currentXP, targetXP);
results.forEach(res => {
const available = currentLvl >= res.reqLevel;
const rowClass = available ? '' : 'calc-unavailable';
const opacity = available ? '1' : '0.5';
html += `
<tr class="${rowClass}" style="opacity: ${opacity}">
<td><strong>${res.name}</strong></td>
<td>${res.reqLevel}</td>
<td>${res.xp}</td>
<td><strong>${res.amount.toLocaleString()}</strong></td>
</tr>
`;
});
}
html += `</table>`;
document.getElementById('calc-results').innerHTML = html;
}
// Inject CSS
const style = document.createElement('style');
style.innerHTML = `
.calc-wrapper {
background: #1a1b26;
color: #a9b1d6;
padding: 20px;
border-radius: 8px;
border: 1px solid #414868;
max-width: 600px;
margin: 20px 0;
font-family: 'Inter', sans-serif;
box-shadow: 0 10px 25px rgba(0,0,0,0.5);
}
.calc-wrapper h2 {
margin-top: 0;
color: #7aa2f7;
border-bottom: 2px solid #24283b;
padding-bottom: 10px;
}
.calc-inputs {
display: flex;
gap: 20px;
margin-bottom: 20px;
}
.calc-input-group {
display: flex;
flex-direction: column;
gap: 5px;
}
.calc-input-group label {
font-size: 12px;
text-transform: uppercase;
font-weight: bold;
color: #565f89;
}
.calc-input-group input {
background: #24283b;
border: 1px solid #414868;
color: #c0caf5;
padding: 10px;
border-radius: 4px;
width: 100px;
font-size: 16px;
font-weight: bold;
}
.calc-input-group input:focus {
outline: none;
border-color: #7aa2f7;
}
.calc-results-header h3 {
color: #bb9af7;
margin: 0 0 5px 0;
}
.calc-table {
width: 100%;
background: transparent !important;
border: none !important;
border-collapse: collapse;
}
.calc-table th {
background: #24283b !important;
color: #7dcfff !important;
border: none !important;
text-align: left;
padding: 10px;
}
.calc-table td {
border: none !important;
border-bottom: 1px solid #24283b !important;
padding: 10px;
color: #c0caf5;
}
.calc-unavailable td {
color: #565f89;
}
.calc-btn {
margin-top: 19px;
background: #7aa2f7;
color: #1a1b26;
border: none;
padding: 10px 20px;
border-radius: 4px;
font-weight: bold;
cursor: pointer;
transition: all 0.2s ease;
}
.calc-btn:hover {
background: #8caaee;
}
`;
document.head.appendChild(style);
// Initial Layout Setup
calcContainer.innerHTML = `
<div class="calc-wrapper">
<h2>${currentSkill} Calculator</h2>
<div class="calc-inputs">
<div class="calc-input-group">
<label>Current Level</label>
<input type="number" id="calc-current-lvl" value="1" min="1" max="99">
</div>
<div class="calc-input-group">
<label>Target Level</label>
<input type="number" id="calc-target-lvl" value="10" min="2" max="99">
</div>
<button class="calc-btn" id="calc-refresh-btn">Calculate</button>
</div>
<div id="calc-results"></div>
</div>
`;
document.getElementById('calc-current-lvl').addEventListener('change', renderCalculator);
document.getElementById('calc-target-lvl').addEventListener('change', renderCalculator);
document.getElementById('calc-refresh-btn').addEventListener('click', renderCalculator);
// Render initially
renderCalculator();
});