feat: polish gameplay and admin flow
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env node
|
||||
// Downloads stratagem icons from helldivers.wiki.gg
|
||||
// Saves as public/icons/<slug>.svg (same filenames as before)
|
||||
|
||||
import { createWriteStream, mkdirSync } from 'fs';
|
||||
import { join, dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import https from 'https';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const OUT_DIR = join(__dirname, '..', 'public', 'icons');
|
||||
const BASE_URL = 'https://helldivers.wiki.gg/images/';
|
||||
|
||||
mkdirSync(OUT_DIR, { recursive: true });
|
||||
|
||||
// Maps our stratagem slug → wiki filename (without _Stratagem_Icon.svg suffix)
|
||||
const WIKI_MAP = {
|
||||
reinforce: 'Reinforce',
|
||||
resupply: 'Resupply',
|
||||
sos_beacon: 'SOS_Beacon',
|
||||
hellbomb: 'Hellbomb',
|
||||
seaf_artillery: 'SEAF_Artillery',
|
||||
upload_data: 'Start_Upload',
|
||||
eagle_rearm: 'Eagle_Rearm',
|
||||
prospecting_drill: 'Prospecting_Drill',
|
||||
|
||||
orbital_gatling_barrage: 'Orbital_Gatling_Barrage',
|
||||
orbital_airburst_strike: 'Orbital_Airburst_Strike',
|
||||
orbital_120mm_he_barrage: 'Orbital_120mm_HE_Barrage',
|
||||
orbital_380mm_he_barrage: 'Orbital_380mm_HE_Barrage',
|
||||
orbital_walking_barrage: 'Orbital_Walking_Barrage',
|
||||
orbital_laser: 'Orbital_Laser',
|
||||
orbital_railcannon_strike: 'Orbital_Railcannon_Strike',
|
||||
orbital_precision_strike: 'Orbital_Precision_Strike',
|
||||
orbital_gas_strike: 'Orbital_Gas_Strike',
|
||||
orbital_ems_strike: 'Orbital_EMS_Strike',
|
||||
orbital_smoke_strike: 'Orbital_Smoke_Strike',
|
||||
orbital_illumination_flare: 'Orbital_Illumination_Flare',
|
||||
|
||||
eagle_strafing_run: 'Eagle_Strafing_Run',
|
||||
eagle_airstrike: 'Eagle_Airstrike',
|
||||
eagle_cluster_bomb: 'Eagle_Cluster_Bomb',
|
||||
eagle_napalm_airstrike: 'Eagle_Napalm_Airstrike',
|
||||
lift_850_jump_pack: 'Jump_Pack',
|
||||
eagle_smoke_strike: 'Eagle_Smoke_Strike',
|
||||
eagle_110mm_rocket_pods: 'Eagle_110mm_Rocket_Pods',
|
||||
eagle_500kg_bomb: 'Eagle_500kg_Bomb',
|
||||
|
||||
patriot_exosuit: 'Patriot_Exosuit',
|
||||
emancipator_exosuit: 'Emancipator_Exosuit',
|
||||
tesla_tower: 'Tesla_Tower',
|
||||
shield_generator_relay: 'Shield_Generator_Relay',
|
||||
|
||||
machine_gun: 'Machine_Gun',
|
||||
anti_materiel_rifle: 'Anti-Materiel_Rifle',
|
||||
stalwart: 'Stalwart',
|
||||
expendable_anti_tank: 'Expendable_Anti-Tank',
|
||||
recoilless_rifle: 'Recoilless_Rifle',
|
||||
flamethrower: 'Flamethrower',
|
||||
autocannon: 'Autocannon',
|
||||
heavy_machine_gun: 'Heavy_Machine_Gun',
|
||||
airburst_rocket_launcher: 'Airburst_Rocket_Launcher',
|
||||
commando: 'Commando',
|
||||
railgun: 'Railgun',
|
||||
spear: 'Spear',
|
||||
quasar_cannon: 'Quasar_Cannon',
|
||||
arc_thrower: 'Arc_Thrower',
|
||||
laser_cannon: 'Laser_Cannon',
|
||||
grenade_launcher: 'Grenade_Launcher',
|
||||
|
||||
supply_pack: 'Supply_Pack',
|
||||
guard_dog_rover: 'Rover',
|
||||
guard_dog: 'Guard_Dog',
|
||||
ballistic_shield_backpack: 'Ballistic_Shield_Backpack',
|
||||
shield_generator_pack: 'Shield_Generator_Pack',
|
||||
directional_shield: 'Directional_Shield',
|
||||
hmg_emplacement: 'HMG_Emplacement',
|
||||
|
||||
anti_personnel_minefield: 'Anti-Personnel_Minefield',
|
||||
incendiary_mines: 'Incendiary_Mines',
|
||||
anti_tank_mines: 'Anti-Tank_Mines',
|
||||
|
||||
machine_gun_sentry: 'Machine_Gun_Sentry',
|
||||
gatling_sentry: 'Gatling_Sentry',
|
||||
mortar_sentry: 'Mortar_Sentry',
|
||||
autocannon_sentry: 'Autocannon_Sentry',
|
||||
rocket_sentry: 'Rocket_Sentry',
|
||||
ems_mortar_sentry: 'EMS_Mortar_Sentry',
|
||||
|
||||
anti_tank_emplacement: 'Anti-Tank_Emplacement',
|
||||
};
|
||||
|
||||
function download(url, dest) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const file = createWriteStream(dest);
|
||||
const request = (targetUrl) => {
|
||||
https.get(targetUrl, { headers: { 'User-Agent': 'helldivers-trainer-bot/1.0' } }, (res) => {
|
||||
if (res.statusCode === 301 || res.statusCode === 302) {
|
||||
file.destroy();
|
||||
return request(res.headers.location);
|
||||
}
|
||||
if (res.statusCode !== 200) {
|
||||
file.destroy();
|
||||
return reject(new Error(`HTTP ${res.statusCode}`));
|
||||
}
|
||||
res.pipe(file);
|
||||
file.on('finish', () => file.close(resolve));
|
||||
}).on('error', reject);
|
||||
};
|
||||
request(url);
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const entries = Object.entries(WIKI_MAP);
|
||||
let ok = 0, fail = 0;
|
||||
|
||||
for (const [slug, wikiName] of entries) {
|
||||
const filename = wikiName + '_Stratagem_Icon.svg';
|
||||
const url = BASE_URL + filename;
|
||||
const dest = join(OUT_DIR, slug + '.svg');
|
||||
try {
|
||||
await download(url, dest);
|
||||
console.log(`✓ ${slug}`);
|
||||
ok++;
|
||||
} catch (err) {
|
||||
console.error(`✗ ${slug} (${err.message})`);
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\nDone: ${ok} ok, ${fail} failed`);
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user