Skip to content

Instantly share code, notes, and snippets.

@jjcf89
Created October 27, 2026 14:41
Show Gist options
  • Select an option

  • Save jjcf89/6818d677cb74542dfd2b0d474cc330e8 to your computer and use it in GitHub Desktop.

Select an option

Save jjcf89/6818d677cb74542dfd2b0d474cc330e8 to your computer and use it in GitHub Desktop.
evolve_achievement_report.js
/**
* EVOLVE WIKI ACHIEVEMENT TRACKER
*
* AGENT INSTRUCTIONS FOR MODIFICATION:
* 1. DOM STRUCTURE: The script relies on <h2> headers for category titles (e.g., "Genus").
* The achievements are inside the next sibling element (usually a div.achieveList).
* 2. STATUS TRACKING: Completion is determined by looking for '.flair' icons with
* the title "Gold". To change to "Missing" mode, filter by '.has-text-fade' class instead.
* 3. NAME MAPPING: Game internal names are extracted from the element ID (e.g., 'a-atmo_rage').
* The regex in `formatName` strips prefixes like 'a-', 'genus_', 'atmo_', etc.
* 4. ADDING SECTIONS: To add a new category, call `getNeededItems('NewCategoryName')`
* and add a corresponding <h2> and <pre> block in the `htmlReport` string.
*/
(function() {
// --- 1. CONFIGURATION & SELECTORS ---
const planetWikiUrl = "https://pmotschmann.github.io/Evolve/wiki.html#planets-gameplay";
const speciesWikiUrl = "https://pmotschmann.github.io/Evolve/wiki.html#races-species";
// Select the currently active UI tabs (e.g. "Missing", "Evil")
const activeFilters = Array.from(document.querySelectorAll('.b-tabs .tabs li.is-active'))
.map(li => li.innerText.trim())
.join(' / ');
// --- 2. CORE UTILITIES ---
/**
* Checks if the achievement container has a Gold Flair icon.
* Edit the .includes('gold') part to track Silver or other tiers.
*/
const isGoldStatus = (el) => {
const icons = el.closest('.achievement').querySelectorAll('.flair');
return Array.from(icons).some(icon =>
icon.title && icon.title.toLowerCase().includes('gold')
);
};
/**
* Cleans internal IDs into human-readable property names.
* Regex removes 'a-' prefix and technical category prefixes.
*/
const formatName = (id) => {
let name = id.replace(/^a-(genus_|biome_|atmo_|extinct_)?/, '').replace(/_/g, ' ');
return name.charAt(0).toUpperCase() + name.slice(1);
};
/**
* Standard extractor for simple lists (Genus and Species)
*/
const getNeededItems = (sectionTitle) => {
const header = Array.from(document.querySelectorAll('h2')).find(el => el.innerText.includes(sectionTitle));
if (!header) return [];
return Array.from(header.nextElementSibling.querySelectorAll('.achieve'))
.filter(el => !isGoldStatus(el))
.map(el => formatName(el.id));
};
// --- 3. PLANET-SPECIFIC LOGIC ---
// The Planet section is unique because it combines Biomes and Traits (Atmosphere/Gravity).
const biomesNeeded = [];
const traitsNeeded = [];
const planetHeader = Array.from(document.querySelectorAll('h2')).find(el => el.innerText.includes('Planet'));
const planetItems = planetHeader ? planetHeader.nextElementSibling.querySelectorAll('.achievement') : [];
planetItems.forEach(achContainer => {
const el = achContainer.querySelector('.achieve');
if (el && !isGoldStatus(el)) {
const name = formatName(el.id);
// Sort by internal ID tags
const isBiome = el.id.includes('biome_') || ['hellscape', 'eden', 'toxic', 'mellow'].some(key => el.id.includes(key));
if (isBiome) {
biomesNeeded.push(name);
} else if (el.id !== 'a-explorer') { // Skip the generic 'Verrazzano' explorer achievement
traitsNeeded.push(name);
}
}
});
// --- 4. DATA COMPILATION ---
const genusNeeded = getNeededItems('Genus');
const speciesNeeded = getNeededItems('Species');
// --- 5. REPORT GENERATION ---
const htmlReport = `
<!DOCTYPE html>
<html>
<head>
<title>Evolve Achievement Report</title>
<style>
body {
font-family: sans-serif;
padding: 15px;
line-height: 1.2;
background: #1a1a1a;
color: #eee;
font-size: 20px;
}
h2 {
color: #f5bb41;
border-bottom: 1px solid #444;
margin: 15px 0 5px 0;
font-size: 18px;
font-weight: bold;
}
h2 a {
color: #f5bb41;
text-decoration: none;
}
h2 a:hover {
text-decoration: underline;
}
pre {
background: #2a2a2a;
padding: 10px;
border-radius: 5px;
white-space: pre-wrap;
font-size: 20px;
color: #fff;
font-family: inherit;
margin: 0;
}
.c {
font-size: 16px;
color: #bbb;
margin: 0 0 10px 0;
}
</style>
</head>
<body>
<p class="c">Filter: ${activeFilters} (No Gold)</p>
<h2><a href="${speciesWikiUrl}" target="_blank">GENUS NEEDED</a></h2>
<pre>${genusNeeded.join(', ') || 'None'}</pre>
<h2><a href="${planetWikiUrl}" target="_blank">BIOMES NEEDED</a></h2>
<pre>${biomesNeeded.join(', ') || 'None'}</pre>
<h2><a href="${planetWikiUrl}" target="_blank">TRAITS NEEDED</a></h2>
<pre>${traitsNeeded.join(', ') || 'None'}</pre>
<h2><a href="${speciesWikiUrl}" target="_blank">SPECIES NEEDED</a></h2>
<pre>${speciesNeeded.join(', ') || 'None'}</pre>
</body>
</html>`;
// --- 6. OUTPUT ---
const reportWindow = window.open("", "_blank");
reportWindow.document.write(htmlReport);
reportWindow.document.close();
})();
@jjcf89

jjcf89 commented Oct 27, 2026

Copy link
Copy Markdown
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment