HWHT ToE Module

ToE Counter Picker & AutoToE for HWH Tweaker

Ten skrypt nie powinien być instalowany bezpośrednio. Jest to biblioteka dla innych skyptów do włączenia dyrektywą meta // @require https://update.greasyfork.org/scripts/569616/1774147/HWHT%20ToE%20Module.js

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Greasemonkey lub Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Violentmonkey.

Aby zainstalować ten skrypt, wymagana będzie instalacja rozszerzenia Tampermonkey lub Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

Aby zainstalować ten skrypt, musisz zainstalować rozszerzenie menedżera skryptów użytkownika.

(Mam już menedżera skryptów użytkownika, pozwól mi to zainstalować!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Musisz zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

(Mam już menedżera stylów użytkownika, pozwól mi to zainstalować!)

// ==UserScript==
// @name            HWHT ToE Module
// @namespace       http://tampermonkey.net/
// @version         1.0.0
// @description     ToE Counter Picker & AutoToE for HWH Tweaker
// @author          AI Assistant
// @license         MIT
// @match           https://www.hero-wars.com/*
// @match           https://apps-1701433570146040.apps.fbsbx.com/*
// @run-at          document-idle
// @grant           unsafeWindow
// ==/UserScript==

// debugLog stub - uses Tweaker's version when available, falls back to console
function debugLog(...args) {
    if (window._tweakerDebugLog) return window._tweakerDebugLog(...args);
    if (localStorage.getItem('hwh_debug_mode') === 'true') console.log('[ToE]', ...args);
}

// Wait for game dependencies
(function waitForDeps() {
    const check = () => {
        return typeof cheats !== 'undefined' && cheats.translate &&
               typeof Caller !== 'undefined' && Caller.send &&
               typeof getToeCounterData === 'function';
    };
    if (check()) { initToEModule(); return; }
    let attempts = 0;
    const timer = setInterval(() => {
        attempts++;
        if (check()) { clearInterval(timer); initToEModule(); }
        else if (attempts > 60) { clearInterval(timer); console.warn('[ToE Module] Dependencies not found after 120s'); }
    }, 2000);
})();

function initToEModule() {


//
// ToE Counter Picker v2 - Smart team selection with auto-retry
//

const ToeCounterPicker = (() => {
    let counterDB = {};
    let titanNameToId = {};
    let titanIdToName = {};
    let initialized = false;
    let ownedTitanIds = [];

    // Retry tracking
    let triedCounters = {};      // { rivalId: Set of tried keys }
    let currentRivalId = null;   // Who we're currently fighting
    let currentCounter = null;   // What counter we used
    let retryInProgress = false; // Prevent double-retry

    // Build titan name lookups from game library
    const buildTitanMappings = () => {
        titanNameToId = {};
        titanIdToName = {};
        if (typeof cheats === 'undefined' || !cheats.translate) return false;

        for (let id = 4000; id < 4050; id++) {
            try {
                const name = cheats.translate('LIB_HERO_NAME_' + id);
                if (name && !name.startsWith('LIB_HERO_NAME_')) {
                    titanNameToId[name.toLowerCase()] = id;
                    titanIdToName[id] = name;
                }
            } catch (e) {}
        }
        debugLog(`[ToE] Built mappings for ${Object.keys(titanIdToName).length} titans`);
        return true;
    };

    // Load counter database
    const loadCounterData = () => {
        const TOE_COUNTER_DATA = getToeCounterData();
        if (!TOE_COUNTER_DATA) return false;
        buildTitanMappings();
        counterDB = {};

        for (const [winRate, attackerStr, defenderStr] of TOE_COUNTER_DATA) {
            const attackerNames = attackerStr.split(',');
            const defenderNames = defenderStr.split(',');
            const attackerIds = attackerNames.map(n => titanNameToId[n.toLowerCase()]).filter(Boolean);
            const defenderIds = defenderNames.map(n => titanNameToId[n.toLowerCase()]).filter(Boolean);

            if (attackerIds.length !== 5 || defenderIds.length !== 5) continue;

            const defKey = defenderIds.slice().sort((a,b) => a-b).join('_');
            if (!counterDB[defKey]) counterDB[defKey] = [];

            const attackKey = attackerIds.slice().sort((a,b) => a-b).join('_');
            if (!counterDB[defKey].some(c => c.key === attackKey)) {
                counterDB[defKey].push({ attackerNames, attackerIds, winRate, key: attackKey });
            }
        }

        for (const defKey in counterDB) {
            counterDB[defKey].sort((a, b) => b.winRate - a.winRate);
        }

        initialized = true;
        console.log(`[ToE] Loaded ${Object.keys(counterDB).length} defender teams`);
        return true;
    };

    // Get owned titan IDs from multiple sources
    const getOwnedTitanIds = () => {
        if (ownedTitanIds.length > 0) return ownedTitanIds;
        if (window._myTitans?.length > 0) { ownedTitanIds = window._myTitans; return ownedTitanIds; }
        if (window.gameLoadData?.titans) {
            const ids = Object.keys(window.gameLoadData.titans).map(id => parseInt(id));
            if (ids.length > 0) { ownedTitanIds = ids; return ids; }
        }
        return [];
    };

    const loadOwnedTitans = async () => {
        try {
            const titans = await Caller.send('titanGetAll');
            ownedTitanIds = Object.keys(titans).map(id => parseInt(id));
            window._myTitans = ownedTitanIds;
            window._myTitansFull = Object.values(titans);
            debugLog(`[ToE] Loaded ${ownedTitanIds.length} owned titans`);
            if (Object.keys(counterDB).length < 200) loadCounterData();
        } catch (e) {}
    };

    // Element fallback
    const ELEMENT_MAP = { 0: 'water', 1: 'fire', 2: 'earth', 3: 'dark', 4: 'light' };
    const ELEMENT_ADVANTAGE = { water: 'fire', fire: 'earth', earth: 'water', dark: 'light', light: 'dark' };
    const getTitanElement = (id) => ELEMENT_MAP[Math.floor((id % 100) / 10)] || 'neutral';

    const getElementFallbackTeam = (enemyTitanIds) => {
        let titans = window._myTitansFull?.length > 0 ? [...window._myTitansFull] :
        window.gameLoadData?.titans ? Object.values(window.gameLoadData.titans) : null;
        if (!titans || titans.length < 5) return null;

        const enemyElements = {};
        for (const id of enemyTitanIds) {
            const elem = getTitanElement(id);
            enemyElements[elem] = (enemyElements[elem] || 0) + 1;
        }
        const dominantEnemy = Object.entries(enemyElements).sort((a, b) => b[1] - a[1])[0]?.[0];
        const counterElement = ELEMENT_ADVANTAGE[dominantEnemy];

        titans.sort((a, b) => {
            const elemA = getTitanElement(a.id), elemB = getTitanElement(b.id);
            const scoreA = elemA === counterElement ? 2 : (elemA === 'dark' || elemA === 'light' ? 1 : 0);
            const scoreB = elemB === counterElement ? 2 : (elemB === 'dark' || elemB === 'light' ? 1 : 0);
            if (scoreA !== scoreB) return scoreB - scoreA;
            return (b.power || 0) - (a.power || 0);
        });

        const team = titans.slice(0, 5).map(t => t.id);
        const names = team.map(id => titanIdToName[id] || `#${id}`);
        return { team, names, winRate: 0, matchType: `element (vs ${dominantEnemy})`, key: 'element_' + dominantEnemy };
    };

    // Find counter, skipping already-tried ones
    const findCounter = (enemyTitanIds, rivalId = null) => {
        if (!initialized) loadCounterData();
        if (!enemyTitanIds || enemyTitanIds.length !== 5) return null;

        const owned = new Set(getOwnedTitanIds());
        const tried = triedCounters[rivalId] || new Set();
        const enemySet = new Set(enemyTitanIds);
        const defKey = enemyTitanIds.slice().sort((a,b) => a-b).join('_');

        // 1. Exact matches
        const exactCounters = counterDB[defKey] || [];
        for (const counter of exactCounters) {
            if (tried.has(counter.key)) {
                debugLog(`[ToE] Skip tried: ${counter.attackerNames.join(', ')}`);
                continue;
            }
            if (counter.attackerIds.every(id => owned.has(id))) {
                return { team: counter.attackerIds, names: counter.attackerNames,
                        winRate: counter.winRate, matchType: 'exact', key: counter.key };
            }
        }

        // 2. Fuzzy matches (4/5)
        let bestFuzzy = null;
        for (const [key, counters] of Object.entries(counterDB)) {
            const dbTitans = key.split('_').map(Number);
            const matchCount = dbTitans.filter(id => enemySet.has(id)).length;
            if (matchCount >= 4) {
                for (const counter of counters) {
                    if (tried.has(counter.key)) continue;
                    if (counter.attackerIds.every(id => owned.has(id))) {
                        const adjustedRate = Math.round(counter.winRate * (matchCount / 5));
                        if (!bestFuzzy || adjustedRate > bestFuzzy.winRate) {
                            bestFuzzy = { team: counter.attackerIds, names: counter.attackerNames,
                                         winRate: adjustedRate, matchType: `fuzzy (${matchCount}/5)`, key: counter.key };
                        }
                    }
                }
            }
        }
        if (bestFuzzy && !tried.has(bestFuzzy.key)) return bestFuzzy;

        // 3. Element fallback
        const elementKey = 'element_fallback';
        if (!tried.has(elementKey)) {
            const elem = getElementFallbackTeam(enemyTitanIds);
            if (elem) { elem.key = elementKey; return elem; }
        }

        return null;
    };

    // Get counter for rival object
    const getCounterForRival = (rival, rivalId) => {
        if (!rival?.titans) return null;
        let titanList = Array.isArray(rival.titans) ? rival.titans : Object.values(rival.titans);
        const enemyIds = titanList.map(t => parseInt(t.id || t));
        return findCounter(enemyIds, rivalId);
    };

    // Retry management
    const markTried = (rivalId, key) => {
        if (!triedCounters[rivalId]) triedCounters[rivalId] = new Set();
        triedCounters[rivalId].add(key);
        console.log(`[ToE] Marked tried: ${key}`);
    };
    const clearTried = () => { triedCounters = {}; currentRivalId = null; currentCounter = null; };
    const setCurrentBattle = (rivalId, counter) => { currentRivalId = rivalId; currentCounter = counter; };
    const getCurrentBattle = () => ({ rivalId: currentRivalId, counter: currentCounter });

    // Auto-retry on loss
    const handleBattleEnd = async (win, cachedRivals) => {
        if (retryInProgress) return;

        const { rivalId, counter } = getCurrentBattle();
        if (!rivalId || !counter) return;

        if (win) {
            console.log(`[ToE] ✓ Won with ${counter.names.join(', ')}`);
            return;
        }

        // Lost - mark and retry
        console.log(`[ToE] ✗ Lost with ${counter.names.join(', ')}`);
        markTried(rivalId, counter.key);

        const rival = cachedRivals?.[rivalId];
        if (!rival) return;

        const nextCounter = getCounterForRival(rival, rivalId);
        if (!nextCounter) {
            console.log('[ToE] No more counters to try');
            return;
        }

        console.log(`[ToE] ↻ Retrying with ${nextCounter.names.join(', ')} (${nextCounter.winRate}% ${nextCounter.matchType})`);
        retryInProgress = true;

        try {
            await Caller.send('titanArenaStartBattle', { visitorId: parseInt(rivalId), titans: nextCounter.team });
            setCurrentBattle(rivalId, nextCounter);
        } catch (e) {
            console.warn('[ToE] Retry failed:', e);
        }
        retryInProgress = false;
    };

    const getTitanName = (id) => { if (!initialized) buildTitanMappings(); return titanIdToName[id] || `#${id}`; };
    const getTitanId = (name) => { if (!initialized) buildTitanMappings(); return titanNameToId[name.toLowerCase()] || null; };

    return {
        loadCounterData, loadOwnedTitans, findCounter, getCounterForRival, getElementFallbackTeam,
        getTitanName, getTitanId, getOwnedTitanIds, markTried, clearTried,
        setCurrentBattle, getCurrentBattle, handleBattleEnd,
        get initialized() { return initialized; },
        get counterDB() { return counterDB; },
        get retryInProgress() { return retryInProgress; }
    };
})();

// Initialize when ready
const initToeCounter = () => {
    try {
        const test = cheats.translate('LIB_HERO_NAME_4001');
        if (test && !test.startsWith('LIB_')) { ToeCounterPicker.loadCounterData(); return true; }
    } catch (e) {}
    return false;
};
if (!initToeCounter()) {
    const initInterval = setInterval(() => { if (initToeCounter()) clearInterval(initInterval); }, 2000);
}
unsafeWindow.ToeCounterPicker = window.ToeCounterPicker = ToeCounterPicker;

//
// AutoToE Configuration & UI
//

const AutoToEConfig = {
    _defaults: {
        strategies: ['power','exact', 'meta', 'element'],
        seedRetries: 10,
        maxRetries: 10,
        enabled: { exact: true, meta: true, element: true, power: true },
        customTeam: []  // User's selected fallback team (5 titan IDs)
    },

    // Load from localStorage
    load() {
        try {
            const saved = localStorage.getItem('AutoToEConfig');
            if (saved) {
                const parsed = JSON.parse(saved);
                Object.assign(this, this._defaults, parsed);
            } else {
                Object.assign(this, this._defaults);
            }
        } catch (e) {
            Object.assign(this, this._defaults);
        }
        return this;
    },

    // Save to localStorage
    save() {
        const toSave = {
            strategies: this.strategies,
            seedRetries: this.seedRetries,
            maxRetries: this.maxRetries,
            enabled: this.enabled,
            customTeam: this.customTeam || []
        };
        localStorage.setItem('AutoToEConfig', JSON.stringify(toSave));
        console.log('[AutoToE] Config saved');
    },

    // Reset to defaults
    reset() {
        Object.assign(this, this._defaults);
        this.save();
    }
}.load();

unsafeWindow.AutoToEConfig = window.AutoToEConfig = AutoToEConfig;





//
// Custom Auto ToE with smart counter-picking and retry on loss
//

const AutoToE = {
    running: false,

    get maxRetries() { return AutoToEConfig.maxRetries || 20; },
    get seedRetries() { return AutoToEConfig.seedRetries || 10; },

    async run() {
        if (this.running) { console.log('[AutoToE] Already running'); return null; }
        this.running = true;
        console.log('[AutoToE] Starting...');

        const results = {
            wins: 0,
            losses: 0,
            totalAttempts: 0,
            scoreGained: 0,
            tiersCompleted: 0,
            rivals: []
        };

        try {
            // Get team setup
            const teamData = await Caller.send('teamGetAll');
            const titanTeam = teamData?.titan_arena || [];
            if (titanTeam.length === 0) {
                console.warn('[AutoToE] No titan_arena team set');
            }

            // Load counter data if needed
            if (ToeCounterPicker.getOwnedTitanIds().length === 0) {
                await ToeCounterPicker.loadOwnedTitans();
            }
            if (Object.keys(ToeCounterPicker.counterDB).length < 200) {
                ToeCounterPicker.loadCounterData();
            }

            let startScore = 0;
            let keepGoing = true;

            while (keepGoing && this.running) {
                const status = await Caller.send('titanArenaGetStatus');

                if (!status) {
                    console.log('[AutoToE] Could not get status');
                    break;
                }

                console.log(`[AutoToE] Status: ${status.status}, Tier: ${status.tier}, canRaid: ${status.canRaid}`);

                if (startScore === 0) startScore = status.dailyScore || 0;

                // Check status
                if (status.status === 'disabled') {
                    console.log('[AutoToE] ToE is disabled');
                    break;
                }

                if (status.status === 'peace_time') {
                    console.log('[AutoToE] Peace time - ToE not active');
                    break;
                }

                // Completed tier - advance to next
                if (status.status === 'completed_tier') {
                    console.log(`[AutoToE] ═══ Completing Tier ${status.tier} ═══`);
                    await Caller.send({ name: 'titanArenaCompleteTier', args: {} });
                    results.tiersCompleted++;
                    await this.delay(500);
                    continue; // Loop back to get new status
                }

                // Can raid - use quick raid
                if (status.canRaid) {
                    console.log(`[AutoToE] ═══ Raiding Tier ${status.tier} ═══`);
                    await this.doRaid(titanTeam, results);
                    results.tiersCompleted++;
                    await this.delay(500);
                    continue; // Loop back to check next tier
                }

                // Normal battle - fight unbeaten rivals
                if (!status.rivals || Object.keys(status.rivals).length === 0) {
                    console.log('[AutoToE] No rivals available');
                    break;
                }

                const rivals = Object.entries(status.rivals).filter(([id, rival]) => {
                    return rival.attackScore < 250;
                });

                if (rivals.length === 0) {
                    console.log('[AutoToE] All rivals beaten on tier ' + status.tier);
                    // Check once more for completed_tier status
                    const recheck = await Caller.send('titanArenaGetStatus');
                    if (recheck?.status === 'completed_tier') {
                        console.log(`[AutoToE] ═══ Completing Tier ${recheck.tier} ═══`);
                        await Caller.send({ name: 'titanArenaCompleteTier', args: {} });
                        results.tiersCompleted++;
                        await this.delay(500);
                        continue;
                    }
                    // If still not completed_tier, we're done with this tier
                    console.log('[AutoToE] Tier not completable (not enough score or canRaid=false)');
                    break;
                }

                console.log(`[AutoToE] ═══ Tier ${status.tier}: ${rivals.length} rivals remaining ═══`);

                for (const [rivalId, rival] of rivals) {
                    if (!this.running) break;

                    const result = await this.fightRival(rivalId, rival);
                    results.totalAttempts += result.attempts;
                    results.rivals.push({
                        id: rivalId,
                        name: rival.userData?.name || rivalId,
                        won: result.won,
                        attempts: result.attempts
                    });

                    if (result.won) results.wins++;
                    else results.losses++;

                    await this.delay(300);
                }

                // After fighting all rivals, loop back to check status
                await this.delay(500);
            }

            // Get final score
            const finalStatus = await Caller.send('titanArenaGetStatus');
            results.scoreGained = (finalStatus?.dailyScore || 0) - startScore;

            // Collect daily rewards
            try {
                const rewards = await Caller.send({ name: 'titanArenaFarmDailyReward', args: {} });
                if (rewards && Object.keys(rewards).length > 0) {
                    console.log(`[AutoToE] 🎁 Collected daily rewards:`, Object.keys(rewards).length, 'tiers');
                }
            } catch (e) {
                // May fail if already collected or not enough score
                console.log('[AutoToE] No daily rewards to collect');
            }

            console.log(`[AutoToE] Done! Tiers: ${results.tiersCompleted}, Wins: ${results.wins}, Losses: ${results.losses}, Score: +${results.scoreGained}`);

        } catch (e) {
            console.error('[AutoToE] Error:', e);
        }

        this.running = false;
        return results;
    },

    // Quick raid (when canRaid is true)
    async doRaid(titanTeam, results) {
        try {
            const raidData = await Caller.send({
                name: 'titanArenaStartRaid',
                args: { titans: titanTeam }
            });

            if (!raidData?.rivals) {
                console.log('[AutoToE] Raid returned no data');
                return;
            }

            const { attackers, rivals } = raidData;
            const endResults = {};

            // Calculate all battles
            for (const [rivalId, rival] of Object.entries(rivals)) {
                const battleData = {
                    attackers: attackers,
                    defenders: [rival.team],
                    seed: rival.seed,
                    typeId: rivalId
                };

                const battleResult = await new Promise(resolve => {
                    BattleCalc(battleData, "get_titanClanPvp", resolve);
                });

                endResults[rivalId] = {
                    progress: battleResult.progress,
                    result: battleResult.result
                };

                if (battleResult.result?.win) results.wins++;
                else results.losses++;
            }

            // Submit raid results
            await Caller.send({
                name: 'titanArenaEndRaid',
                args: { results: endResults }
            });

            console.log(`[AutoToE] Raid complete: ${Object.keys(rivals).length} rivals`);

        } catch (e) {
            console.error('[AutoToE] Raid error:', e);
        }
    },


    // ... rest of AutoToE methods (fightRival, findUntriedCounter, tryStrategy, doBattle, delay, stop)

    async fightRival(rivalId, rival) {
        const titanList = Array.isArray(rival.titans) ? rival.titans : Object.values(rival.titans);
        const enemyIds = titanList.map(t => parseInt(t.id));
        const enemyNames = enemyIds.map(id => ToeCounterPicker.getTitanName(id));

        console.log(`[AutoToE] ═══ Rival ${rivalId}: ${enemyNames.join(', ')} ═══`);

        const triedKeys = new Set();
        let attempts = 0;

        while (attempts < this.maxRetries) {
            attempts++;

            // Find a counter we haven't tried
            const counter = this.findUntriedCounter(enemyIds, triedKeys);

            if (!counter) {
                console.log(`[AutoToE] No more counters to try`);
                return { won: false, attempts };
            }

            console.log(`[AutoToE] Attempt ${attempts}: ${counter.names.join(', ')} (${counter.winRate}% ${counter.matchType})`);
            triedKeys.add(counter.key);

            // Start battle
            const battleResult = await this.doBattle(rivalId, counter.team);

            if (battleResult.won) {
                console.log(`[AutoToE] ✓ Won on attempt ${attempts}`);
                return { won: true, attempts };
            }

            console.log(`[AutoToE] ✗ Lost, trying next counter...`);
            await this.delay(300);
        }

        console.log(`[AutoToE] Failed after ${attempts} attempts`);
        return { won: false, attempts };
    },

    findUntriedCounter(enemyIds, triedKeys) {
        const owned = new Set(ToeCounterPicker.getOwnedTitanIds());
        const enemySet = new Set(enemyIds);
        const defKey = enemyIds.slice().sort((a,b) => a-b).join('_');

        for (const strategy of AutoToEConfig.strategies) {
            if (AutoToEConfig.enabled[strategy] === false) continue;

            const result = this.tryStrategy(strategy, { enemyIds, enemySet, defKey, owned, triedKeys });
            if (result) return result;
        }

        return null;
    },

    tryStrategy(strategy, ctx) {
        const { enemyIds, enemySet, defKey, owned, triedKeys } = ctx;

        switch (strategy) {
            case 'exact': {
                const exactCounters = ToeCounterPicker.counterDB[defKey] || [];
                for (const counter of exactCounters) {
                    if (triedKeys.has(counter.key)) continue;
                    if (counter.attackerIds.every(id => owned.has(id))) {
                        return { team: counter.attackerIds, names: counter.attackerNames,
                                winRate: counter.winRate, matchType: 'exact', key: counter.key };
                    }
                }
                break;
            }

            case 'meta': {
                if (typeof TOE_META_TEAMS === 'undefined') break;
                for (let i = 0; i < TOE_META_TEAMS.length; i++) {
                    const metaKey = 'meta_' + i;
                    if (triedKeys.has(metaKey)) continue;

                    const names = TOE_META_TEAMS[i];
                    const team = names.map(n => ToeCounterPicker.getTitanId(n)).filter(Boolean);

                    if (team.length === 5 && team.every(id => owned.has(id))) {
                        return { team, names, winRate: 0, matchType: `meta #${i+1}`, key: metaKey };
                    }
                }
                break;
            }

            case 'element': {
                const elementKey = 'element_fallback';
                if (triedKeys.has(elementKey)) break;
                const elem = ToeCounterPicker.getElementFallbackTeam(enemyIds);
                if (elem) { elem.key = elementKey; return elem; }
                break;
            }

            case 'power': {
                const powerKey = 'power_fallback';
                if (triedKeys.has(powerKey)) break;

                let team, names;
                if (AutoToEConfig.customTeam?.length === 5) {
                    team = AutoToEConfig.customTeam;
                    names = team.map(id => ToeCounterPicker.getTitanName(id));
                } else if (window._myTitansFull?.length >= 5) {
                    const sorted = [...window._myTitansFull].sort((a,b) => (b.power||0) - (a.power||0));
                    team = sorted.slice(0,5).map(t => t.id);
                    names = team.map(id => ToeCounterPicker.getTitanName(id));
                } else {
                    break;
                }

                return { team, names, winRate: 0, matchType: 'custom', key: powerKey };
            }
        }

        return null;
    },

    async doBattle(rivalId, titanTeam) {
        try {
            // Start battle
            const startResult = await Caller.send({
                name: 'titanArenaStartBattle',
                args: {
                    rivalId: parseInt(rivalId),
                    titans: titanTeam
                }
            });

            if (!startResult?.battle) {
                console.error('[AutoToE] No battle data returned');
                return { won: false, error: 'No battle data' };
            }

            // Calculate battle result using game's BattleCalc
            let battleResult = await new Promise(resolve => {
                BattleCalc(startResult.battle, "get_titanClanPvp", e => resolve(e));
            });

            // Try different seeds if first calc loses
            if (!battleResult.result?.win) {
                for (let i = 0; i < AutoToEConfig.seedRetries; i++) {
                    const battle = structuredClone(startResult.battle);
                    battle.seed = Math.floor(Date.now() / 1000) + Math.floor(Math.random() * 1000);
                    const retry = await new Promise(resolve => {
                        BattleCalc(battle, "get_titanClanPvp", e => resolve(e));
                    });
                    if (retry.result?.win) {
                        console.log(`[AutoToE] Found winning seed on try ${i+1}`);
                        battleResult = retry;
                        break;
                    }
                }
            }

            console.log('[AutoToE] Battle calc:', battleResult.result?.win ? 'WIN' : 'LOSE');

            // End battle with calculated result
            const endResult = await Caller.send({
                name: 'titanArenaEndBattle',
                args: {
                    rivalId: parseInt(rivalId),
                    progress: battleResult.progress,
                    result: battleResult.result
                }
            });

            const won = battleResult.result?.win === true;
            return { won, result: endResult, battleResult };

        } catch (e) {
            console.error('[AutoToE] Battle error:', e);
            return { won: false, error: e };
        }
    },

    delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    },

    stop() {
        this.running = false;
        console.log('[AutoToE] Stopped');
    }
};

// Expose globally
unsafeWindow.AutoToE = window.AutoToE = AutoToE;
console.log('[AutoToE] Ready - run with: AutoToE.run()');



//
// AutoToE UI - Summary & Config Popup
//

const AutoToEUI = {
    lastResults: null,

    // Strategy display names
    strategyNames: {
        exact: '📚 Counter Library',
        meta: '⭐ Meta Teams',
        element: '🔥 Element Counter',
        power: '💪 Selected Team'
    },

    // Show config/summary popup
    showPopup(results = null) {
        this.lastResults = results || this.lastResults;

        // Remove existing popup
        document.querySelector('.autotoe-popup')?.remove();

        const popup = document.createElement('div');
        popup.className = 'autotoe-popup';
        popup.innerHTML = `
       <style>
                .autotoe-popup {
                    position: fixed;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%);
                    background: linear-gradient(180deg, #3d2817 0%, #2a1810 100%);
                    border: 3px solid #8b6914;
                    border-radius: 10px;
                    padding: 14px;
                    z-index: 999999;
                    min-width: 360px;
                    max-width: 440px;
                    color: #e8d5b0;
                    font-family: "Twemoji Country Flags", Arial, sans-serif;
                    box-shadow: 0 8px 30px rgba(0,0,0,0.5);
                    font-size: 12px;
                }
                .autotoe-popup h2 {
                    margin: 0 0 10px 0;
                    color: #ffd700;
                    font-size: 16px;
                    display: flex;
                    align-items: center;
                    gap: 8px;
                }
                .autotoe-popup .close-btn {
                    position: absolute;
                    top: 6px;
                    right: 10px;
                    background: none;
                    border: none;
                    color: #8b7355;
                    font-size: 20px;
                    cursor: pointer;
                }
                .autotoe-popup .close-btn:hover { color: #ffd700; }
                .autotoe-popup .tabs {
                    display: flex;
                    gap: 4px;
                    margin-bottom: 10px;
                }
                .autotoe-popup .tab {
                    padding: 5px 12px;
                    background: rgba(139,105,20,0.3);
                    border: 1px solid #5a4a2a;
                    border-radius: 5px;
                    color: #c9a84c;
                    cursor: pointer;
                    font-size: 11px;
                    transition: all 0.15s;
                }
                .autotoe-popup .tab:hover { background: rgba(139,105,20,0.5); }
                .autotoe-popup .tab.active { background: #8b6914; color: #fff; border-color: #8b6914; }
                .autotoe-popup .tab-content { display: none; }
                .autotoe-popup .tab-content.active { display: block; }
                .autotoe-popup .config-section {
                    background: rgba(0,0,0,0.2);
                    border: 1px solid #5a4a2a;
                    border-radius: 6px;
                    padding: 8px 10px;
                    margin-bottom: 8px;
                }
                .autotoe-popup .config-section h3 {
                    margin: 0 0 6px 0;
                    font-size: 12px;
                    color: #ffd700;
                }
                .autotoe-popup .strategy-list {
                    list-style: none;
                    padding: 0;
                    margin: 0;
                }
                .autotoe-popup .strategy-item {
                    display: flex;
                    align-items: center;
                    gap: 8px;
                    padding: 5px 6px;
                    background: rgba(0,0,0,0.15);
                    border: 1px solid transparent;
                    border-radius: 4px;
                    margin-bottom: 3px;
                    cursor: grab;
                    font-size: 11px;
                }
                .autotoe-popup .strategy-item:hover { border-color: #5a4a2a; }
                .autotoe-popup .strategy-item:active { cursor: grabbing; }
                .autotoe-popup .strategy-item.dragging { opacity: 0.5; }
                .autotoe-popup .strategy-item .drag-handle { color: #5a4a2a; font-size: 14px; }
                .autotoe-popup .strategy-item label { flex: 1; cursor: pointer; color: #e8d5b0; }
                .autotoe-popup .strategy-item input[type="checkbox"] {
                    width: 15px;
                    height: 15px;
                    cursor: pointer;
                    accent-color: #4ae29a;
                }
                .autotoe-popup .input-row {
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    margin-bottom: 6px;
                }
                .autotoe-popup .input-row label { color: #c9a84c; font-size: 11px; }
                .autotoe-popup .input-row input[type="number"] {
                    width: 50px;
                    padding: 3px 6px;
                    border: 1px solid #5a4a2a;
                    border-radius: 4px;
                    background: rgba(0,0,0,0.3);
                    color: #ffd700;
                    font-size: 12px;
                    text-align: center;
                }
                .autotoe-popup .btn-row {
                    display: flex;
                    gap: 6px;
                    margin-top: 10px;
                }
                .autotoe-popup .btn {
                    flex: 1;
                    padding: 7px 12px;
                    border: none;
                    border-radius: 5px;
                    font-size: 12px;
                    cursor: pointer;
                    transition: all 0.15s;
                }
                .autotoe-popup .btn-primary {
                    background: #8b6914;
                    color: #fff;
                    border: 1px solid #a67c00;
                }
                .autotoe-popup .btn-primary:hover { background: #a67c00; }
                .autotoe-popup .btn-secondary {
                    background: rgba(0,0,0,0.3);
                    color: #c9a84c;
                    border: 1px solid #5a4a2a;
                }
                .autotoe-popup .btn-secondary:hover { background: rgba(139,105,20,0.3); }
                .autotoe-popup .btn-success {
                    background: linear-gradient(180deg, #4a8b3a 0%, #2d6620 100%);
                    color: #fff;
                    border: 1px solid #5a9e45;
                }
                .autotoe-popup .btn-success:hover { background: linear-gradient(180deg, #5a9e45 0%, #3a7a2a 100%); }
                .autotoe-popup .summary-grid {
                    display: grid;
                    grid-template-columns: 1fr 1fr 1fr 1fr;
                    gap: 6px;
                }
                .autotoe-popup .summary-card {
                    background: rgba(0,0,0,0.2);
                    border: 1px solid #5a4a2a;
                    border-radius: 6px;
                    padding: 8px;
                    text-align: center;
                }
                .autotoe-popup .summary-card .value {
                    font-size: 20px;
                    font-weight: bold;
                    color: #ffd700;
                }
                .autotoe-popup .summary-card .label {
                    font-size: 10px;
                    color: #8b7355;
                    margin-top: 2px;
                }
                .autotoe-popup .rival-list {
                    max-height: 160px;
                    overflow-y: auto;
                    margin-top: 8px;
                }
                .autotoe-popup .rival-item {
                    display: flex;
                    justify-content: space-between;
                    padding: 4px 8px;
                    background: rgba(0,0,0,0.15);
                    border-radius: 3px;
                    margin-bottom: 2px;
                    font-size: 11px;
                }
                .autotoe-popup .rival-item.win { border-left: 3px solid #4ae29a; }
                .autotoe-popup .rival-item.lose { border-left: 3px solid #c94040; }
            </style>

            <button class="close-btn">&times;</button>
            <h2>⚔️ AutoToE</h2>

            <div class="tabs">
                <button class="tab active" data-tab="config">⚙️ Config</button>
                <button class="tab" data-tab="summary">📊 Summary</button>
            </div>

            <div class="tab-content active" data-tab="config">
                <div class="config-section">
                    <h3>📋 Strategy Order (drag to reorder)</h3>
                    <ul class="strategy-list" id="autotoe-strategies">
                        ${this.renderStrategyList()}
                    </ul>
                </div>

                <div class="config-section">
                    <h3>⚡ Battle Settings</h3>
                    <div class="input-row">
                        <label>Max Attempts per Rival:</label>
                        <input type="number" id="autotoe-maxRetries" value="${AutoToEConfig.maxRetries}" min="1" max="50">
                    </div>
                    <div class="input-row">
                        <label>Seed Retries per Battle:</label>
                        <input type="number" id="autotoe-seedRetries" value="${AutoToEConfig.seedRetries}" min="0" max="50">
                    </div>
                </div>

<div class="config-section">
                    <h3>💪 Selected Team</h3>
                    <div style="display: flex; justify-content: space-between; align-items: center;">
                        <span style="color: #ccc; font-size: 12px;">
                            ${AutoToEConfig.customTeam?.length === 5
            ? AutoToEConfig.customTeam.map(id => ToeCounterPicker.getTitanName(id)).join(', ')
        : 'Not set (using top 5 by power)'}
                        </span>
                        <button class="btn btn-secondary" id="autotoe-select-team" style="flex: 0; padding: 6px 12px;">Select</button>
                    </div>
                </div>

                <div class="btn-row">
                    <button class="btn btn-secondary" id="autotoe-reset">Reset Defaults</button>
                    <button class="btn btn-primary" id="autotoe-save">💾 Save</button>
                </div>
            </div>

            <div class="tab-content" data-tab="summary">
                ${this.renderSummary()}
            </div>

            <div class="btn-row">
                <button class="btn btn-success" id="autotoe-run" style="font-size: 16px;">
                    ▶️ Start AutoToE Raid
                </button>
            </div>
        `;

        document.body.appendChild(popup);
        this.attachEvents(popup);
    },

    renderStrategyList() {
        const allStrategies = ['exact', 'meta', 'element', 'power'];
        const ordered = [...AutoToEConfig.strategies];

        // Add any missing strategies at the end
        for (const s of allStrategies) {
            if (!ordered.includes(s)) ordered.push(s);
        }

        return ordered.map(s => `
            <li class="strategy-item" data-strategy="${s}" draggable="true">
                <span class="drag-handle">☰</span>
                <input type="checkbox" id="strat-${s}" ${AutoToEConfig.enabled[s] !== false ? 'checked' : ''}>
                <label for="strat-${s}">${this.strategyNames[s] || s}</label>
            </li>
        `).join('');
    },

    renderSummary() {
        if (!this.lastResults) {
            return `
                <div style="text-align: center; color: #888; padding: 30px;">
                    No raid results yet.<br>Run AutoToE to see summary.
                </div>
            `;
        }

        const r = this.lastResults;
        return `
            <div class="summary-grid">
                <div class="summary-card">
                    <div class="value" style="color: #00d26a;">${r.wins}</div>
                    <div class="label">Wins</div>
                </div>
                <div class="summary-card">
                    <div class="value" style="color: #e94560;">${r.losses}</div>
                    <div class="label">Losses</div>
                </div>
                <div class="summary-card">
                    <div class="value">${r.totalAttempts || 0}</div>
                    <div class="label">Total Attempts</div>
                </div>
                <div class="summary-card">
                    <div class="value">${r.scoreGained || 0}</div>
                    <div class="label">Score Gained</div>
                </div>
            </div>
            <div class="rival-list">
                ${(r.rivals || []).map(rival => `
                    <div class="rival-item ${rival.won ? 'win' : 'lose'}">
                        <span>${rival.name || rival.id}</span>
                        <span>${rival.won ? '✓ Won' : '✗ Lost'} (${rival.attempts} tries)</span>
                    </div>
                `).join('')}
            </div>
        `;
    },

    attachEvents(popup) {
        // Close button
        popup.querySelector('.close-btn').onclick = () => popup.remove();

        // Tab switching
        popup.querySelectorAll('.tab').forEach(tab => {
            tab.onclick = () => {
                popup.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
                popup.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
                tab.classList.add('active');
                popup.querySelector(`.tab-content[data-tab="${tab.dataset.tab}"]`).classList.add('active');
            };
        });

        // Drag and drop for strategy reordering
        const strategyList = popup.querySelector('#autotoe-strategies');
        let draggedItem = null;

        strategyList.querySelectorAll('.strategy-item').forEach(item => {
            item.addEventListener('dragstart', (e) => {
                draggedItem = item;
                item.classList.add('dragging');
            });

            item.addEventListener('dragend', () => {
                item.classList.remove('dragging');
                draggedItem = null;
            });

            item.addEventListener('dragover', (e) => {
                e.preventDefault();
                if (draggedItem && draggedItem !== item) {
                    const rect = item.getBoundingClientRect();
                    const midY = rect.top + rect.height / 2;
                    if (e.clientY < midY) {
                        strategyList.insertBefore(draggedItem, item);
                    } else {
                        strategyList.insertBefore(draggedItem, item.nextSibling);
                    }
                }
            });
        });

        // Save button
        popup.querySelector('#autotoe-save').onclick = () => {
            // Get strategy order from DOM
            const strategies = [];
            const enabled = {};
            popup.querySelectorAll('.strategy-item').forEach(item => {
                const s = item.dataset.strategy;
                strategies.push(s);
                enabled[s] = item.querySelector('input[type="checkbox"]').checked;
            });

            AutoToEConfig.strategies = strategies;
            AutoToEConfig.enabled = enabled;
            AutoToEConfig.maxRetries = parseInt(popup.querySelector('#autotoe-maxRetries').value) || 10;
            AutoToEConfig.seedRetries = parseInt(popup.querySelector('#autotoe-seedRetries').value) || 10;
            AutoToEConfig.save();

            // Visual feedback
            const btn = popup.querySelector('#autotoe-save');
            btn.textContent = '✓ Saved!';
            setTimeout(() => btn.textContent = '💾 Save', 1500);
        };

        // Reset button
        popup.querySelector('#autotoe-reset').onclick = () => {
            AutoToEConfig.reset();
            this.showPopup(); // Refresh popup
        };

        // Select team button
        popup.querySelector('#autotoe-select-team').onclick = () => {
            this.showTeamSelector();
        };

        // Run button
        popup.querySelector('#autotoe-run').onclick = async () => {
            const btn = popup.querySelector('#autotoe-run');
            btn.disabled = true;
            btn.textContent = '⏳ Running...';

            try {
                const results = await AutoToE.run();
                this.lastResults = results;

                // Switch to summary tab
                popup.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
                popup.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
                popup.querySelector('.tab[data-tab="summary"]').classList.add('active');
                popup.querySelector('.tab-content[data-tab="summary"]').classList.add('active');
                popup.querySelector('.tab-content[data-tab="summary"]').innerHTML = this.renderSummary();
            } finally {
                btn.disabled = false;
                btn.textContent = '▶️ Start AutoToE Raid';
            }
        };
    },

    async showTeamSelector() {
        document.querySelector('.toe-team-popup')?.remove();

        // Load titan data if not available
        let owned = window._myTitansFull || Object.values(window.gameLoadData?.titans || {});
        if (!owned || owned.length < 5) {
            try {
                const titans = await Caller.send('titanGetAll');
                window._myTitans = Object.keys(titans).map(id => parseInt(id));
                window._myTitansFull = Object.values(titans);
                owned = window._myTitansFull;
                console.log('[AutoToE] Loaded', owned.length, 'titans');
            } catch (e) {
                console.error('[AutoToE] Failed to load titans:', e);
                return;
            }
        }

        if (!owned || owned.length < 5) {
            console.error('[AutoToE] No titan data available');
            return;
        }

        // Sort by power
        const titans = [...owned].sort((a, b) => (b.power || 0) - (a.power || 0));
        const currentTeam = AutoToEConfig.customTeam || [];

        const popup = document.createElement('div');
        popup.className = 'toe-team-popup';
        popup.innerHTML = `
         <style>
                .toe-team-popup {
                    position: fixed;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%);
                    background: linear-gradient(180deg, #3d2817 0%, #2a1810 100%);
                    border: 3px solid #8b6914;
                    border-radius: 10px;
                    padding: 14px;
                    z-index: 1000000;
                    min-width: 380px;
                    max-width: 480px;
                    color: #e8d5b0;
                    font-family: "Twemoji Country Flags", Arial, sans-serif;
                    box-shadow: 0 8px 30px rgba(0,0,0,0.5);
                    font-size: 12px;
                }
                .toe-team-popup h3 {
                    margin: 0 0 6px 0;
                    color: #ffd700;
                    font-size: 14px;
                }
                .toe-team-popup .close-btn {
                    position: absolute;
                    top: 6px;
                    right: 10px;
                    background: none;
                    border: none;
                    color: #8b7355;
                    font-size: 20px;
                    cursor: pointer;
                }
                .toe-team-popup .close-btn:hover { color: #ffd700; }
                .toe-team-popup .selected-team {
                    display: flex;
                    gap: 6px;
                    padding: 8px;
                    background: rgba(0,0,0,0.3);
                    border: 1px solid #5a4a2a;
                    border-radius: 6px;
                    margin-bottom: 10px;
                    min-height: 44px;
                    flex-wrap: wrap;
                    align-items: center;
                }
                .toe-team-popup .selected-titan {
                    display: flex;
                    flex-direction: column;
                    align-items: center;
                    padding: 3px 8px;
                    background: rgba(74,226,154,0.15);
                    border: 1px solid rgba(74,226,154,0.4);
                    border-radius: 4px;
                    font-size: 10px;
                    cursor: pointer;
                }
                .toe-team-popup .selected-titan:hover {
                    background: rgba(201,64,64,0.2);
                    border-color: #c94040;
                }
                .toe-team-popup .selected-titan .power {
                    font-size: 10px;
                    color: #8b7355;
                }
                .toe-team-popup .empty-slot {
                    width: 55px;
                    height: 36px;
                    border: 1px dashed #5a4a2a;
                    border-radius: 4px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    color: #5a4a2a;
                    font-size: 16px;
                }
                .toe-team-popup .titan-grid {
                    display: grid;
                    grid-template-columns: repeat(6, 1fr);
                    gap: 4px;
                    max-height: 240px;
                    overflow-y: auto;
                    padding: 4px;
                }
                .toe-team-popup .titan-card {
                    display: flex;
                    flex-direction: column;
                    align-items: center;
                    padding: 5px 3px;
                    background: rgba(0,0,0,0.2);
                    border: 1px solid transparent;
                    border-radius: 4px;
                    cursor: pointer;
                    transition: all 0.1s;
                    font-size: 10px;
                    text-align: center;
                }
                .toe-team-popup .titan-card:hover {
                    background: rgba(139,105,20,0.2);
                    border-color: #5a4a2a;
                }
                .toe-team-popup .titan-card.selected {
                    background: rgba(74,226,154,0.15);
                    border-color: rgba(74,226,154,0.5);
                }
                .toe-team-popup .titan-card.disabled {
                    opacity: 0.3;
                    cursor: not-allowed;
                }
                .toe-team-popup .titan-card .name {
                    font-weight: bold;
                    color: #e8d5b0;
                    margin-bottom: 1px;
                }
                .toe-team-popup .titan-card .power {
                    font-size: 10px;
                    color: #8b7355;
                }
                .toe-team-popup .titan-card .element {
                    font-size: 10px;
                    padding: 0px 3px;
                    border-radius: 2px;
                    margin-top: 1px;
                }
                .toe-team-popup .elem-fire { background: rgba(255,80,20,0.3); color: #ffa07a; }
                .toe-team-popup .elem-water { background: rgba(30,90,180,0.3); color: #87ceeb; }
                .toe-team-popup .elem-earth { background: rgba(45,100,30,0.3); color: #90ee90; }
                .toe-team-popup .elem-light { background: rgba(180,180,30,0.3); color: #ffff99; }
                .toe-team-popup .elem-dark { background: rgba(100,30,140,0.3); color: #dda0dd; }
                .toe-team-popup .btn-row {
                    display: flex;
                    gap: 6px;
                    margin-top: 10px;
                }
                .toe-team-popup .btn {
                    flex: 1;
                    padding: 7px 12px;
                    border: none;
                    border-radius: 5px;
                    font-size: 12px;
                    cursor: pointer;
                }
                .toe-team-popup .btn-primary {
                    background: #8b6914;
                    color: #fff;
                    border: 1px solid #a67c00;
                }
                .toe-team-popup .btn-primary:hover { background: #a67c00; }
                .toe-team-popup .btn-secondary {
                    background: rgba(0,0,0,0.3);
                    color: #c9a84c;
                    border: 1px solid #5a4a2a;
                }
                .toe-team-popup .hint {
                    font-size: 10px;
                    color: #8b7355;
                    margin-bottom: 8px;
                }
            </style>

            <button class="close-btn">&times;</button>
            <h3>💪 Selected Team</h3>
            <p class="hint">Click titans to add/remove. This team is used when counter library, meta teams, and element counter all fail.</p>

            <div class="selected-team" id="toe-selected-team">
                ${this.renderSelectedTeam(currentTeam)}
            </div>

            <div class="titan-grid" id="toe-titan-grid">
                ${titans.map(t => this.renderTitanCard(t, currentTeam.includes(t.id))).join('')}
            </div>

            <div class="btn-row">
                <button class="btn btn-secondary" id="toe-team-clear">Clear</button>
                <button class="btn btn-primary" id="toe-team-save">💾 Save Team</button>
            </div>
        `;

        document.body.appendChild(popup);

        let selected = [...currentTeam];

        const updateDisplay = () => {
            popup.querySelector('#toe-selected-team').innerHTML = this.renderSelectedTeam(selected);
            popup.querySelectorAll('.titan-card').forEach(card => {
                const id = parseInt(card.dataset.id);
                card.classList.toggle('selected', selected.includes(id));
                card.classList.toggle('disabled', selected.length >= 5 && !selected.includes(id));
            });

            // Click to remove from selected
            popup.querySelectorAll('.selected-titan').forEach(el => {
                el.onclick = () => {
                    const id = parseInt(el.dataset.id);
                    selected = selected.filter(x => x !== id);
                    updateDisplay();
                };
            });
        };

        // Close
        popup.querySelector('.close-btn').onclick = () => popup.remove();

        // Titan selection
        popup.querySelectorAll('.titan-card').forEach(card => {
            card.onclick = () => {
                const id = parseInt(card.dataset.id);
                if (selected.includes(id)) {
                    selected = selected.filter(x => x !== id);
                } else if (selected.length < 5) {
                    selected.push(id);
                }
                updateDisplay();
            };
        });

        // Clear
        popup.querySelector('#toe-team-clear').onclick = () => {
            selected = [];
            updateDisplay();
        };

        // Save
        popup.querySelector('#toe-team-save').onclick = () => {
            if (selected.length !== 5) {
                alert('Please select exactly 5 titans');
                return;
            }
            AutoToEConfig.customTeam = selected;
            AutoToEConfig.save();
            popup.remove();
            console.log('[AutoToE] Custom team saved:', selected.map(id => ToeCounterPicker.getTitanName(id)));
        };

        updateDisplay();
    },

    renderSelectedTeam(teamIds) {
        const slots = [];
        for (let i = 0; i < 5; i++) {
            if (teamIds[i]) {
                const id = teamIds[i];
                const titan = window._myTitansFull?.find(t => t.id === id) ||
                      Object.values(window.gameLoadData?.titans || {}).find(t => t.id === id);
                const name = ToeCounterPicker.getTitanName(id);
                const power = titan?.power || '?';
                slots.push(`
                    <div class="selected-titan" data-id="${id}">
                        <span class="name">${name}</span>
                        <span class="power">${power}</span>
                    </div>
                `);
            } else {
                slots.push('<div class="empty-slot">+</div>');
            }
        }
        return slots.join('');
    },

    renderTitanCard(titan, isSelected) {
        const name = ToeCounterPicker.getTitanName(titan.id);
        const element = this.getTitanElement(titan.id);
        return `
            <div class="titan-card ${isSelected ? 'selected' : ''}" data-id="${titan.id}">
                <span class="name">${name}</span>
                <span class="power">${titan.power || '?'}</span>
                <span class="element elem-${element}">${element}</span>
            </div>
        `;
    },

    getTitanElement(id) {
        const map = { 0: 'water', 1: 'fire', 2: 'earth', 3: 'dark', 4: 'light' };
        return map[Math.floor((id % 100) / 10)] || 'neutral';
    }
};

unsafeWindow.AutoToEUI = window.AutoToEUI = AutoToEUI;

}