// ==UserScript== // @name Eclesiar - Terrain Preset Reminder // @namespace http://tampermonkey.net/ // @version 1.0 // @description Automated terrain preset validation. // @author morswin28 // @match https://eclesiar.com/war/* // @homepageURL https://scripts.ecle.fun/ // @downloadURL https://raw.githubusercontent.com/marsach/ecle/main/eclesiar-terrain-preset-reminder.user.js // @updateURL https://raw.githubusercontent.com/marsach/ecle/main/eclesiar-terrain-preset-reminder.user.js // @grant none // ==/UserScript== (function() { 'use strict'; const STORAGE_KEY = 'ec_allow_presets_cache'; const CACHE_KEY = 'ec_terrain_fetch_cache'; const CACHE_TTL = 60000; let detectedTerrainName = null; let fetchError = false; const terrainTypes = [ { name: 'Plains', asset: '0.png', display: 'Plains/Równiny' }, { name: 'Mountains', asset: '1.png', display: 'Mountains/Góry' }, { name: 'Forest', asset: '2.png', display: 'Forest/Las' }, { name: 'Desert', asset: '3.png', display: 'Desert/Pustynia' } ]; async function fetchBattleData() { const cached = sessionStorage.getItem(CACHE_KEY); if (cached) { const { timestamp, data } = JSON.parse(cached); if (Date.now() - timestamp < CACHE_TTL) { const currentUrl = window.location.href; const match = data.find(item => currentUrl.includes(item.href)); if (match) { detectedTerrainName = match.terrain; return; } } } try { const response = await fetch('https://eclesiar.com/battles'); if (!response.ok) throw new Error(); const htmlText = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(htmlText, 'text/html'); const rows = doc.querySelectorAll('.page-content table tr'); const battlesData = []; rows.forEach(row => { const link = row.querySelector('a[href*="/war/"]'); const img = row.querySelector('img.terrain-type-img'); if (link && img) { const assetName = img.getAttribute('src').split('/').pop(); const match = terrainTypes.find(t => t.asset === assetName); if (match) { battlesData.push({ href: link.getAttribute('href'), terrain: match.name }); } } }); sessionStorage.setItem(CACHE_KEY, JSON.stringify({ timestamp: Date.now(), data: battlesData })); const currentUrl = window.location.href; const currentMatch = battlesData.find(item => currentUrl.includes(item.href)); if (currentMatch) detectedTerrainName = currentMatch.terrain; else fetchError = true; } catch (e) { fetchError = true; } } function getStoredData() { const data = localStorage.getItem(STORAGE_KEY); try { return data ? JSON.parse(data) : {}; } catch (e) { return {}; } } function saveToStorage() { const data = {}; document.querySelectorAll('.select-terrain-config').forEach(select => { const terrainName = select.getAttribute('data-terrain'); data[terrainName] = Array.from(select.selectedOptions).map(opt => opt.value); }); localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); updateValidationStatus(); } function updateValidationStatus() { const fightBtn = document.querySelector('.fight-button p'); if (!fightBtn) return; let statusSpan = document.getElementById('preset-validation-inline'); if (!statusSpan) { statusSpan = document.createElement('span'); statusSpan.id = 'preset-validation-inline'; statusSpan.style.cssText = 'margin-left: 10px; font-size: 0.85em; display: inline-block;'; fightBtn.appendChild(statusSpan); } if (fetchError) { statusSpan.innerHTML = `[Błąd terenu]`; return; } if (!detectedTerrainName) { statusSpan.innerHTML = ''; return; } const activeSlot = document.querySelector('.preset-slot.active span'); const activePresetId = activeSlot ? activeSlot.innerText.trim() : null; const allowedPresets = getStoredData()[detectedTerrainName] || []; if (allowedPresets.length === 0) { statusSpan.innerHTML = `[?]`; } else if (activePresetId && allowedPresets.includes(activePresetId)) { statusSpan.innerHTML = `[OK]`; } else { statusSpan.innerHTML = `[ZŁY PRESET!]`; } } async function initUI() { if (document.querySelector('.tier-settings')) return; await fetchBattleData(); const presetArea = document.querySelector('.preset-slot-area'); if (!presetArea) return; const settingsBtn = document.createElement('div'); settingsBtn.className = 'preset-slot c-tooltip right equipment-item tier-settings'; settingsBtn.style.cssText = 'cursor: pointer; display: flex; align-items: center; justify-content: center; background: #2c3e50;'; const isReady = !fetchError && detectedTerrainName; settingsBtn.innerHTML = isReady ? `