MWI角色名片插件

MWI角色名片插件 - 一键生成角色名片

当前为 2025-08-03 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         MWI角色名片插件
// @namespace    http://tampermonkey.net/
// @version      1.3.1
// @license      MIT
// @description  MWI角色名片插件 - 一键生成角色名片
// @author       Windoge
// @match        https://www.milkywayidle.com/*
// @grant        GM_getValue
// @grant        GM_setValue
// @run-at       document-idle
// @require      https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js
// ==/UserScript==

(function() {
    'use strict';

    // 使用立即执行函数避免全局变量污染
    const MWICharacterCard = (function() {
        const isZH = navigator.language.includes('zh');
        
        // 检测移动端
        function isMobile() {
            return window.innerWidth <= 768 || /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
        }
        
        // 简化的SVG创建工具
        class CharacterCardSVGTool {
            constructor() {
                this.isLoaded = true; // 简化:直接设为true
                this.spriteSheets = {
                    items: '/static/media/items_sprite.6d12eb9d.svg',
                    skills: '/static/media/skills_sprite.57eb3a30.svg',
                    abilities: '/static/media/abilities_sprite.38932ac3.svg',
                    misc: '/static/media/misc_sprite.6b3198dc.svg'
                };
            }

            async loadSpriteSheets() {
                console.log('SVG sprite系统已初始化');
                console.log('Sprite文件路径:', this.spriteSheets);
                this.isLoaded = true;
                return true;
            }

            // 创建MWI风格的SVG图标 - 直接返回HTML字符串
            createSVGIcon(itemId, options = {}) {
                const { className = 'Icon_icon__2LtL_', title = itemId, type = 'items' } = options;
                const svgHref = `${this.spriteSheets[type]}#${itemId}`;
                
                // 收集调试信息
                if (!state.debugInfo.firstSvgPath) {
                    state.debugInfo.firstSvgPath = svgHref;
                }
                state.debugInfo.iconCount++;
                
                return `<svg role="img" aria-label="${title}" class="${className}" width="100%" height="100%">
                    <use href="${svgHref}"></use>
                </svg>`;
            }

            // 后备图标
            createFallbackIcon(itemId, className, title) {
                const text = itemId.length > 6 ? itemId.substring(0, 6) : itemId;
                return `<div class="${className}" title="${title}" style="
                    width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
                    background: #4a90e2; color: white; font-size: 10px; border-radius: 4px;
                ">${text}</div>`;
            }

            hasIcon() { return this.isLoaded; }
        }

        // 技能选择器相关函数
        function showSkillSelector(skillIndex) {
            // 获取所有可用技能(包括未装备的)
            const allSkills = window.characterCardWebSocketData?.characterAbilities || [];
            const availableSkills = allSkills
                .filter(ability => ability.abilityHrid && ability.abilityHrid.startsWith("/abilities/"))
                .sort((a, b) => (a.slotNumber || 0) - (b.slotNumber || 0));
            
            // 创建技能选择器模态框
            const modal = document.createElement('div');
            modal.className = 'skill-selector-modal';
            modal.innerHTML = `
                <div class="skill-selector-content">
                    <div class="skill-selector-header">
                        <h3>${isZH ? '选择技能' : 'Select Skill'}</h3>
                        <button class="close-skill-selector">&times;</button>
                    </div>
                    <div class="skill-selector-grid">
                        <!-- 空按钮 -->
                        <div class="skill-option empty-skill-option" data-skill-index="${skillIndex}" data-ability-hrid="" data-level="0">
                            <div class="skill-option-icon">
                                <div class="empty-skill-icon">-</div>
                            </div>
                            <div class="skill-option-level">${isZH ? '空' : 'Empty'}</div>
                        </div>
                        ${availableSkills.map(skill => `
                            <div class="skill-option" data-skill-index="${skillIndex}" data-ability-hrid="${skill.abilityHrid}" data-level="${skill.level}">
                                <div class="skill-option-icon">
                                    ${createSvgIcon(skill.abilityHrid, 'abilities')}
                                </div>
                                <div class="skill-option-level">Lv.${skill.level}</div>
                            </div>
                        `).join('')}
                    </div>
                </div>
            `;
            
            // 添加事件监听器
            modal.querySelector('.close-skill-selector').onclick = () => {
                document.body.removeChild(modal);
            };
            modal.onclick = (e) => {
                if (e.target === modal) {
                    document.body.removeChild(modal);
                }
            };
            
            // 添加技能选项点击事件监听器
            const skillOptions = modal.querySelectorAll('.skill-option');
            skillOptions.forEach(option => {
                option.addEventListener('click', function() {
                    const skillIndex = parseInt(this.getAttribute('data-skill-index'));
                    const abilityHrid = this.getAttribute('data-ability-hrid');
                    const level = parseInt(this.getAttribute('data-level'));
                    selectSkill(skillIndex, abilityHrid, level);
                });
            });
            
            document.body.appendChild(modal);
        }
        
        function selectSkill(skillIndex, abilityHrid, level) {
            // 更新用户选择的技能
            if (abilityHrid === "") {
                // 选择"空"选项,删除该位置的技能
                delete state.customSkills.selectedSkills[skillIndex];
            } else {
                // 选择具体技能
                state.customSkills.selectedSkills[skillIndex] = {
                    abilityHrid: abilityHrid,
                    level: level,
                    slotNumber: skillIndex + 1
                };
            }
            
                            // 重新生成技能面板
                const characterCard = document.querySelector('#character-card');
                if (characterCard) {
                    const skillPanel = characterCard.querySelector('.skill-panel');
                    if (skillPanel) {
                        // 重新生成技能面板内容
                        const characterData = {
                            abilities: window.characterCardWebSocketData?.characterAbilities || [],
                            characterSkills: window.characterCardWebSocketData?.characterSkills || []
                        };
                        const newSkillPanel = generateSkillPanel(characterData, true);
                        skillPanel.innerHTML = newSkillPanel.replace(/<div class="skill-panel">([\s\S]*?)<\/div>$/, '$1');
                        
                        // 重新添加事件监听器
                        const skillSlots = skillPanel.querySelectorAll('.skill-slot, .empty-skill-slot');
                        skillSlots.forEach(slot => {
                            slot.addEventListener('click', function() {
                                const skillIndex = parseInt(this.getAttribute('data-skill-index'));
                                showSkillSelector(skillIndex);
                            });
                        });
                    }
                }
            
            // 关闭技能选择器
            const modal = document.querySelector('.skill-selector-modal');
            if (modal) {
                document.body.removeChild(modal);
            }
        }
        
        // 全局版本号
        const VERSION = '1.3.1';
        
        // 使用闭包管理状态,避免全局变量
        const state = {
            svgTool: new CharacterCardSVGTool(),
            debugInfo: {
                firstSvgPath: null,
                iconCount: 0
            },
            observer: null,
            timer: null,
            isInitialized: false,
            // 用户自定义技能展示状态
            customSkills: {
                selectedSkills: [], // 用户选择的技能列表
                maxSkills: 8 // 最大技能数量
            }
        };

        // 简化的SVG图标创建函数
        function createSvgIcon(itemHrid, iconType = null, className = 'Icon_icon__2LtL_') {
            // 自动检测图标类型和提取itemId
            let type = 'items';
            let itemId = itemHrid;
            
            if (itemHrid.startsWith('/items/')) {
                type = 'items';
                itemId = itemHrid.replace('/items/', '');
            } else if (itemHrid.startsWith('/abilities/')) {
                type = 'abilities';
                itemId = itemHrid.replace('/abilities/', '');
            } else if (itemHrid.startsWith('/skills/')) {
                type = 'skills';
                itemId = itemHrid.replace('/skills/', '');
            } else if (itemHrid.startsWith('/misc/')) {
                type = 'misc';
                itemId = itemHrid.replace('/misc/', '');
            } else {
                // 对于基础属性图标
                if (['stamina', 'intelligence', 'attack', 'power', 'defense', 'ranged', 'magic'].includes(itemHrid)) {
                    type = 'skills';
                    itemId = itemHrid;
                } else {
                    itemId = itemHrid.replace("/items/", "").replace("/abilities/", "").replace("/skills/", "").replace("/misc/", "");
                }
            }
            
            // 如果手动指定了类型,使用指定的类型
            if (iconType) {
                type = iconType;
            }
            
            // 使用SVG工具创建图标
            if (state.svgTool && state.svgTool.isLoaded) {
                return state.svgTool.createSVGIcon(itemId, { 
                    className: className, 
                    title: itemId,
                    type: type
                });
            }
            
            // 后备方案
            return state.svgTool.createFallbackIcon(itemId, className, itemId);
        }

        function generateEquipmentPanel(characterObj) {
            // MWI装备槽位映射 - 使用grid位置
            const equipmentSlots = {
                "/item_locations/back": { row: 1, col: 1, name: "背部" },
                "/item_locations/head": { row: 1, col: 2, name: "头部" },
                "/item_locations/main_hand": { row: 2, col: 1, name: "主手" },
                "/item_locations/body": { row: 2, col: 2, name: "身体" },
                "/item_locations/off_hand": { row: 2, col: 3, name: "副手" },
                "/item_locations/hands": { row: 3, col: 1, name: "手部" },
                "/item_locations/legs": { row: 3, col: 2, name: "腿部" },
                "/item_locations/pouch": { row: 3, col: 3, name: "口袋" },
                "/item_locations/feet": { row: 4, col: 2, name: "脚部" },
                "/item_locations/neck": { row: 1, col: 5, name: "项链" },
                "/item_locations/earrings": { row: 2, col: 5, name: "耳环" },
                "/item_locations/ring": { row: 3, col: 5, name: "戒指" },
                "/item_locations/trinket": { row: 4, col: 5, name: "饰品" },
                "/item_locations/two_hand": { row: 2, col: 1, name: "双手" }
            };

            let items = characterObj.equipment || characterObj.characterItems || [];
            const equipmentMap = {};
            let hasTwoHandWeapon = false;

            // 构建装备映射
            items.forEach(item => {
                const slotInfo = equipmentSlots[item.itemLocationHrid];
                if (slotInfo) {
                    equipmentMap[item.itemLocationHrid] = item;
                    if (item.itemLocationHrid === "/item_locations/two_hand") hasTwoHandWeapon = true;
                }
            });

            // 创建MWI风格的装备面板
            let html = '<div class="equipment-panel">';
            html += `<div class="panel-title">${isZH ? '装备' : 'Equipment'}</div>`;
            html += '<div class="EquipmentPanel_playerModel__3LRB6" style="margin-top:40px">';
            
            // 遍历所有装备槽位
            Object.entries(equipmentSlots).forEach(([slotHrid, slotInfo]) => {
                // 如果有双手武器,跳过单手主手槽
                if (hasTwoHandWeapon && slotHrid === "/item_locations/main_hand") {
                    return;
                }

                // 如果没有双手武器,跳过双手槽
                if (!hasTwoHandWeapon && slotHrid === "/item_locations/two_hand") {
                    return;
                }
                
                const item = equipmentMap[slotHrid];
                
                html += `<div style="grid-row-start: ${slotInfo.row}; grid-column-start: ${slotInfo.col};">`;
                html += '<div class="ItemSelector_itemSelector__2eTV6">';
                html += '<div class="ItemSelector_itemContainer__3olqe">';
                html += '<div class="Item_itemContainer__x7kH1">';
                html += '<div>';
                
                if (item) {
                    // 有装备的槽位
                    const itemName = item.itemHrid.replace('/items/', '');
                    const enhancementLevel = item.enhancementLevel || 0;
                    
                    html += '<div class="Item_item__2De2O Item_clickable__3viV6" style="position: relative;">';
                    html += '<div class="Item_iconContainer__5z7j4">';
                    html += createSvgIcon(item.itemHrid, 'items'); // 使用MWI的Icon类
                    html += '</div>';
                    
                    // 强化等级 - 完全按照MWI原生格式
                    if (enhancementLevel > 0) {
                        html += `<div class="Item_enhancementLevel__19g-e enhancementProcessed enhancementLevel_${enhancementLevel}" style="z-index: 9">+${enhancementLevel}</div>`;
                    }
                    
                    html += '</div>';
                } else {
                    // 空装备槽
                    html += '<div class="Item_item__2De2O" style="position: relative; opacity: 0.3;">';
                    html += '<div class="Item_iconContainer__5z7j4">';
                    html += `<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; color: #999; font-size: 10px;">${isZH ? '空' : 'Empty'}</div>`;
                    html += '</div>';
                    html += '</div>';
                }
                
                html += '</div>';
                html += '</div>';
                html += '</div>';
                html += '</div>';
                html += '</div>';
            });
            
            html += '</div>'; // EquipmentPanel_playerModel__3LRB6
            html += '</div>'; // equipment-panel
            
            return html;
        }

        // 从页面获取战斗等级
        function calculateCombatLevel(characterObj) {
            try {
                // 获取各项属性等级
                const stamina = characterObj.staminaLevel || 0;
                const intelligence = characterObj.intelligenceLevel || 0;
                const defense = characterObj.defenseLevel || 0;
                const attack = characterObj.attackLevel || 0;
                const power = characterObj.powerLevel || 0;
                const ranged = characterObj.rangedLevel || 0;
                const magic = characterObj.magicLevel || 0;
                
                // 计算公式:战斗等级 = 0.2 * (耐力 + 智力 + 防御) + 0.4 * MAX(0.5 * (攻击 + 力量), 远程, 魔法)
                const baseCombat = 0.2 * (stamina + intelligence + defense);
                const attackPower = 0.5 * (attack + power);
                const maxCombat = Math.max(attackPower, ranged, magic);
                const combatLevel = Math.floor(baseCombat + 0.4 * maxCombat);
                
                return combatLevel;
            } catch (error) {
                console.log('计算战斗等级失败:', error);
                return 0;
            }
        }

        function getCombatLevelFromPage() {
            try {
                // 查找包含战斗等级信息的元素
                const overviewTab = document.querySelector('.SharableProfile_overviewTab__W4dCV');
                if (overviewTab) {
                    // 查找包含"战斗等级:"文本的div元素
                    const combatLevelDiv = Array.from(overviewTab.querySelectorAll('div')).find(div => 
                        div.textContent && div.textContent.includes('战斗等级:')
                    );
                    
                    if (combatLevelDiv) {
                        // 提取数字
                        const match = combatLevelDiv.textContent.match(/战斗等级:\s*(\d+)/);
                        if (match && match[1]) {
                            return parseInt(match[1]);
                        }
                    }
                }
            } catch (error) {
                console.log('获取战斗等级失败:', error);
            }
            return 0;
        }

        function generateAbilityPanel(characterObj) {
            const abilityMapping = [
                { key: "staminaLevel", name: isZH ? "耐力" : "Stamina", icon: "stamina" },
                { key: "intelligenceLevel", name: isZH ? "智力" : "Intelligence", icon: "intelligence" },
                { key: "attackLevel", name: isZH ? "攻击" : "Attack", icon: "attack" },
                { key: "powerLevel", name: isZH ? "力量" : "Power", icon: "power" },
                { key: "defenseLevel", name: isZH ? "防御" : "Defense", icon: "defense" },
                { key: "rangedLevel", name: isZH ? "远程" : "Ranged", icon: "ranged" },
                { key: "magicLevel", name: isZH ? "魔法" : "Magic", icon: "magic" }
            ];

            let html = '<div class="ability-panel">';
            html += `<div class="panel-title">${isZH ? '属性等级' : 'Abilities'}</div><div class="ability-list">`;
            
            // 添加战斗等级作为第一行
            const combatLevel = calculateCombatLevel(characterObj);
            html += `<div class="ability-row">
                <div class="ability-icon">
                    <svg role="img" aria-label="combat" class="Icon_icon__2LtL_" width="100%" height="100%">
                        <use href="/static/media/misc_sprite.6b3198dc.svg#combat"></use>
                    </svg>
                </div>
                <span style="flex: 1;">${isZH ? '战斗' : 'Combat'}</span>
                <span class="level">Lv.${combatLevel}</span>
            </div>`;
            
            abilityMapping.forEach(ability => {
                let level = 0;
                if (characterObj[ability.key]) {
                    level = characterObj[ability.key];
                } else if (characterObj.characterSkills) {
                    const skillKey = ability.key.replace('Level', '');
                    const skill = characterObj.characterSkills.find(skill => skill.skillHrid.includes(`/skills/${skillKey}`));
                    level = skill ? skill.level : 0;
                }
                
                html += `<div class="ability-row">
                    <div class="ability-icon">${createSvgIcon(ability.icon, 'skills')}</div>
                    <span style="flex: 1;">${ability.name}</span>
                    <span class="level">Lv.${level}</span>
                </div>`;
            });
            
            return html + '</div></div>';
        }

        function generateSkillPanel(data, isMyCharacter = false) {
            let abilities = data.abilities || data.characterSkills || [];
            
            let combatSkills;
            
            if (isMyCharacter) {
                // 场景2:根据slotNumber筛选和排序
                combatSkills = abilities
                    .filter(ability => ability.abilityHrid && ability.abilityHrid.startsWith("/abilities/"))
                    .filter(ability => ability.slotNumber && ability.slotNumber > 0)
                    .sort((a, b) => a.slotNumber - b.slotNumber); // 按slotNumber升序排列
                
                // 初始化用户选择的技能(如果为空)
                if (state.customSkills.selectedSkills.length === 0) {
                    // 默认显示前5个技能
                    state.customSkills.selectedSkills = combatSkills.slice(0, 5).map(skill => ({
                        abilityHrid: skill.abilityHrid,
                        level: skill.level,
                        slotNumber: skill.slotNumber
                    }));
                }
                
                let html = '<div class="skill-panel">';
                html += `<div class="panel-title">${isZH ? '技能等级' : 'Skills'}</div>`;
                
                // 使用MWI原生的技能网格容器
                html += '<div class="AbilitiesPanel_abilityGrid__-p-VF">';
                
                // 渲染用户选择的技能(最多8个)
                for (let i = 0; i < state.customSkills.maxSkills; i++) {
                    const selectedSkill = state.customSkills.selectedSkills[i];
                    
                    if (selectedSkill) {
                        // 显示已选择的技能
                        html += '<div>';
                        html += `<div class="Ability_ability__1njrh Ability_clickable__w9HcM skill-slot" data-skill-index="${i}">`;
                        html += '<div class="Ability_iconContainer__3syNQ">';
                        html += createSvgIcon(selectedSkill.abilityHrid, 'abilities');
                        html += '</div>';
                        html += `<div class="Ability_level__1L-do">Lv.${selectedSkill.level}</div>`;
                        html += '</div>';
                        html += '</div>';
                    } else {
                        // 显示空白位置(鼠标悬停时显示虚线边框)
                        html += '<div>';
                        html += `<div class="Ability_ability__1njrh Ability_clickable__w9HcM empty-skill-slot" data-skill-index="${i}">`;
                        html += '</div>';
                        html += '</div>';
                    }
                }
                
                html += '</div>'; // AbilitiesPanel_abilityGrid__-p-VF
                html += '</div>'; // skill-panel
                
                return html;
            } else {
                // 场景1:保持原始顺序,不排序
                combatSkills = abilities
                    .filter(ability => ability.abilityHrid && ability.abilityHrid.startsWith("/abilities/"));
                
                let html = '<div class="skill-panel">';
                html += `<div class="panel-title">${isZH ? '技能等级' : 'Skills'}</div>`;
                
                // 使用MWI原生的技能网格容器
                html += '<div class="AbilitiesPanel_abilityGrid__-p-VF">';
                
                // 渲染每个技能
                combatSkills.forEach(ability => {
                    const abilityId = ability.abilityHrid.replace('/abilities/', '');
                    
                    html += '<div>';
                    html += '<div class="Ability_ability__1njrh Ability_clickable__w9HcM">';
                    html += '<div class="Ability_iconContainer__3syNQ">';
                    html += createSvgIcon(ability.abilityHrid, 'abilities'); // 使用完整的hrid
                    html += '</div>';
                    html += `<div class="Ability_level__1L-do">Lv.${ability.level}</div>`;
                    html += '</div>';
                    html += '</div>';
                });
                
                html += '</div>'; // AbilitiesPanel_abilityGrid__-p-VF
                html += '</div>'; // skill-panel
                
                return html;
            }
        }

        function generateHousePanel(data) {
            const houseRoomsMapping = [
                { hrid: "/house_rooms/dining_room", icon: "stamina", name: isZH ? "餐厅" : "Dining Room" },
                { hrid: "/house_rooms/library", icon: "intelligence", name: isZH ? "图书馆" : "Library" },
                { hrid: "/house_rooms/dojo", icon: "attack", name: isZH ? "道场" : "Dojo" },
                { hrid: "/house_rooms/gym", icon: "power", name: isZH ? "健身房" : "Gym" },
                { hrid: "/house_rooms/armory", icon: "defense", name: isZH ? "军械库" : "Armory" },
                { hrid: "/house_rooms/archery_range", icon: "ranged", name: isZH ? "射箭场" : "Archery Range" },
                { hrid: "/house_rooms/mystical_study", icon: "magic", name: isZH ? "神秘研究室" : "Mystical Study" }
            ];

            let houseRoomMap = data.houseRooms || data.characterHouseRoomMap || {};

            let html = '<div class="house-panel">';
            html += `<div class="panel-title">${isZH ? '房屋等级' : 'House Rooms'}</div>`;
            
            // 使用和技能面板相同的MWI原生结构
            html += '<div class="AbilitiesPanel_abilityGrid__-p-VF">';
            
            // 遍历所有房屋类型
            houseRoomsMapping.forEach(houseRoom => {
                let level = 0;
                if (houseRoomMap[houseRoom.hrid]) {
                    level = typeof houseRoomMap[houseRoom.hrid] === 'object' 
                        ? houseRoomMap[houseRoom.hrid].level || 0 
                        : houseRoomMap[houseRoom.hrid];
                }
                
                // 使用和技能相同的MWI原生结构
                html += '<div>';
                html += '<div class="Ability_ability__1njrh Ability_clickable__w9HcM">';
                html += '<div class="Ability_iconContainer__3syNQ">';
                html += createSvgIcon(houseRoom.icon, 'skills'); // 使用标准的Icon类
                html += '</div>';
                // 为8级房屋添加特殊显示
                let levelText = '';
                let levelClass = 'Ability_level__1L-do';
                
                if (level === 8) {
                    levelText = `Lv.8`;
                    levelClass += ' house-max-level';
                } else if (level > 0) {
                    levelText = `Lv.${level}`;
                } else {
                    levelText = isZH ? '未建造' : 'Lv.0';
                }
                
                html += `<div class="${levelClass}">${levelText}</div>`;
                html += '</div>';
                html += '</div>';
            });
            
            html += '</div>'; // AbilitiesPanel_abilityGrid__-p-VF
            html += '</div>'; // house-panel
            
            return html;
        }

        function generateCharacterCard(data, characterName, characterNameElement = null, isMyCharacter = false) {
            let characterObj = data.player || data;
            const equipmentPanel = generateEquipmentPanel(characterObj);
            
            // 创建标题栏内容
            let headerContent = '';
            if (characterNameElement) {
                // 使用从页面复制的角色信息元素
                headerContent = characterNameElement;
            } else {
                // 后备方案:使用简单的角色名
                headerContent = `<h2>${characterName}</h2>`;
            }
            
            return `
                <div id="character-card" class="character-card">
                    <div class="card-header">${headerContent}</div>
                    <div class="card-content">
                        ${equipmentPanel}
                        ${generateAbilityPanel(characterObj)}
                        ${generateSkillPanel(data, isMyCharacter)}
                        ${generateHousePanel(data)}
                    </div>
                </div>
            `;
        }

        function createModalStyles() {
            const style = document.createElement('style');
            style.textContent = `
                .character-card-modal {
                    position: fixed; top: 0; left: 0; width: 100%; height: 100%;
                    background: rgba(0, 0, 0, 0.8); z-index: 10000; display: flex;
                    justify-content: center; align-items: center; padding: 16px; box-sizing: border-box;
                }
                .modal-content {
                    background: white; border-radius: 15px; padding: 20px;
                    max-width: 90vw; max-height: 90vh; overflow: auto; position: relative;
                }
                .close-modal {
                    position: absolute; top: 10px; right: 15px; background: none;
                    border: none; font-size: 24px; cursor: pointer; color: #666; z-index: 1;
                }
                .close-modal:hover { color: #000; }
                .character-card {
                    background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
                    border: 2px solid #4a90e2; border-radius: 15px; padding: 20px; color: white;
                    font-family: 'Arial', sans-serif; max-width: 800px; margin: 0 auto;
                    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
                }
                .card-header {
                    text-align: center; margin-bottom: 20px; border-bottom: 2px solid #4a90e2; padding-bottom: 10px;
                }
                .card-header h2 {
                    margin: 0; color: #4a90e2; font-size: 24px; text-shadow: 0 0 10px rgba(74, 144, 226, 0.5);
                }
                
                /* 角色信息元素在名片中的样式 */
                .card-header .CharacterName_characterName__2FqyZ {
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    flex-wrap: wrap;
                    gap: 8px;
                }
                
                .card-header .CharacterName_chatIcon__22lxV {
                    width: 32px;
                    height: 32px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                }
                
                .card-header .CharacterName_name__1amXp {
                    font-size: 20px;
                    font-weight: bold;
                    text-shadow: 0 0 10px rgba(74, 144, 226, 0.5);
                }
                
                .card-header .CharacterName_gameMode__2Pvw8 {
                    font-size: 14px;
                    opacity: 0.8;
                }
                .card-content {
                    display: grid; grid-template-columns: 1fr 0.7fr; grid-template-rows: auto 1fr; gap: 20px;
                }
                .equipment-panel, .house-panel, .ability-panel, .skill-panel {
                    background: rgba(255, 255, 255, 0.1); border-radius: 10px; padding: 6px;
                    border: 1px solid rgba(74, 144, 226, 0.3);
                }
                .panel-title {
                    margin: 0 0 15px 0; color: #4a90e2; font-size: 16px;
                    border-bottom: 1px solid rgba(74, 144, 226, 0.3); padding-bottom: 5px; text-align: center;
                }
                .equipment-panel { grid-column: 1; grid-row: 1; }
                
                /* 只为模态框内的装备面板添加网格布局,不影响游戏原生UI */
                .character-card .EquipmentPanel_playerModel__3LRB6 {
                    display: grid;
                    grid-template-columns: repeat(5, 1fr);
                    grid-template-rows: repeat(4, auto);
                    gap: 8px;
                    padding: 10px;
                    max-width: 350px;
                    margin: 0 auto;
                }
                
                /* 确保装备槽的基本布局 */
                .character-card .ItemSelector_itemSelector__2eTV6 {
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    min-height: 60px;
                }
                
                /* 技能面板样式 - 仅作用于角色名片内 */
                .character-card .AbilitiesPanel_abilityGrid__-p-VF {
                    display: grid;
                    grid-template-columns: repeat(4, 1fr);
                    gap: 8px;
                    padding: 10px;
                    max-height: 180px;
                    overflow-y: auto;
                }
                
                /* 技能项容器 */
                .character-card .Ability_ability__1njrh {
                    display: flex;
                    flex-direction: column;
                    align-items: center;
                    justify-content: center;
                    min-height: 70px;
                    border-radius: 8px;
                    background: rgba(255, 255, 255, 0.05);
                    border: 1px solid rgba(74, 144, 226, 0.3);
                    transition: all 0.2s ease;
                }
                
                .character-card .Ability_ability__1njrh.Ability_clickable__w9HcM:hover {
                    background: rgba(74, 144, 226, 0.1);
                    border-color: #4a90e2;
                    transform: scale(1.05);
                }
                
                /* 技能图标容器 */
                .character-card .Ability_iconContainer__3syNQ {
                    width: 36px;
                    height: 36px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    margin-bottom: 4px;
                }
                
                /* 房屋等级图标容器 - 调整垂直居中 */
                .character-card .house-panel .Ability_iconContainer__3syNQ {
                    width: 36px;
                    height: 36px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    margin-bottom: 4px;
                    transform: translateY(2px);
                }
                
                /* 技能等级文字 */
                .character-card .Ability_level__1L-do {
                    font-size: 12px;
                    font-weight: bold;
                    color: #fff;
                    text-align: center;
                }
                
                /* 房屋最高等级特殊样式 */
                .character-card .house-max-level {
                    color: #ff8c00 !important;
                    font-weight: bold;
                    text-shadow: 0 0 4px rgba(255, 140, 0, 0.5);
                }
                .ability-panel { grid-column: 2; grid-row: 1; }
                .ability-list { flex: 1; }
                .ability-row {
                    display: flex; align-items: center; margin-bottom: 8px; padding: 4px; border-radius: 4px;
                }
                .ability-icon {
                    width: 30px; height: 30px; margin-right: 10px; display: flex;
                    align-items: center; justify-content: center;
                }
                .house-panel { 
                    grid-column: 1; 
                    grid-row: 2; 
                }
                

                .skill-panel { 
                    grid-column: 2; 
                    grid-row: 2; 
                }
                .level { color: #fff; font-weight: bold; }
                @media (max-width: 768px) {
                    /* 移动端模态框调整 */
                    .character-card-modal {
                        padding: 8px;
                    }
                    
                    .modal-content {
                        max-width: 95vw;
                        max-height: 95vh;
                        padding: 12px;
                        overflow-y: auto;
                    }
                    
                    /* 移动端单列布局 */
                    .card-content { 
                        grid-template-columns: 1fr; 
                        grid-template-rows: auto auto auto auto; 
                        gap: 12px;
                    }
                    
                    .equipment-panel { grid-column: 1; grid-row: 1; }
                    .ability-panel { grid-column: 1; grid-row: 2; }
                    .house-panel { grid-column: 1; grid-row: 3; }
                    .skill-panel { grid-column: 1; grid-row: 4; }
                    
                    /* 移动端面板样式调整 */
                    .equipment-panel, .house-panel, .ability-panel, .skill-panel {
                        padding: 10px;
                        margin-bottom: 4px;
                    }
                    
                    /* 移动端装备面板调整 - 保持游戏原始布局 */
                    .character-card .EquipmentPanel_playerModel__3LRB6 {
                        gap: 6px;
                        padding: 8px;
                        max-width: 100%;
                    }
                    
                    /* 移动端技能面板调整 - 每行4个 */
                    .character-card .ability-panel .AbilitiesPanel_abilityGrid__-p-VF {
                        grid-template-columns: repeat(4, 1fr);
                        gap: 10px;
                        padding: 12px;
                        max-height: 180px;
                    }
                    
                    /* 移动端房屋面板调整 - 每行4个 */
                    .character-card .house-panel .AbilitiesPanel_abilityGrid__-p-VF {
                        grid-template-columns: repeat(4, 1fr);
                        gap: 8px;
                        padding: 10px;
                        max-height: 180px;
                    }
                    
                    /* 移动端技能卡片间距调整 */
                    .character-card .ability-panel .Ability_ability__1njrh {
                        margin: 2px;
                        min-height: 75px;
                    }
                    
                    /* 移动端房屋卡片间距调整 - 4列布局 */
                    .character-card .house-panel .Ability_ability__1njrh {
                        margin: 1px;
                        min-height: 65px;
                        font-size: 11px;
                    }
                    
                    /* 移动端房屋等级图标容器 - 调整垂直居中 */
                    .character-card .house-panel .Ability_iconContainer__3syNQ {
                        transform: translateY(1px);
                    }
                    
                    /* 移动端面板标题调整 */
                    .panel-title {
                        font-size: 14px;
                        margin-bottom: 8px;
                        padding-bottom: 4px;
                    }
                    
                    /* 移动端字体调整 */
                    .character-card {
                        font-size: 12px;
                    }
                    
                    /* 移动端指示横幅调整 */
                    .instruction-banner {
                        padding: 8px;
                        font-size: 14px;
                    }
                }
                
                .instruction-banner {
                    background: #17a2b8; color: white; padding: 10px; border-radius: 5px;
                    margin-bottom: 10px; font-weight: bold; text-align: center;
                }
                
                .download-section {
                    text-align: center; margin-bottom: 15px;
                }
                
                .download-card-btn {
                    background: #28a745; color: white; border: none; padding: 8px 16px;
                    border-radius: 5px; font-size: 14px; font-weight: bold; cursor: pointer;
                    transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                }
                
                .download-card-btn:hover:not(:disabled) {
                    background: #218838; transform: translateY(-1px);
                    box-shadow: 0 4px 8px rgba(0,0,0,0.15);
                }
                
                .download-card-btn:disabled {
                    background: #6c757d; cursor: not-allowed; transform: none;
                    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                }
                
                /* 技能提示样式 */
                .skill-hint {
                    margin-top: 8px;
                    text-align: center;
                }
                
                .skill-hint span {
                    font-size: 12px;
                    color: #17a2b8;
                    font-style: italic;
                    background: rgba(23, 162, 184, 0.1);
                    padding: 4px 8px;
                    border-radius: 4px;
                    border: 1px solid rgba(23, 162, 184, 0.3);
                }
                
                /* 按钮行样式 */
                .button-row {
                    display: flex;
                    gap: 8px;
                    justify-content: center;
                    align-items: center;
                    margin-bottom: 8px;
                }
                
                .save-skill-config-btn,
                .load-skill-config-btn {
                    background: #17a2b8;
                    color: white;
                    border: none;
                    padding: 6px 12px;
                    border-radius: 4px;
                    font-size: 12px;
                    cursor: pointer;
                    transition: all 0.2s ease;
                    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                }
                
                .save-skill-config-btn:hover,
                .load-skill-config-btn:hover {
                    background: #138496;
                    transform: translateY(-1px);
                    box-shadow: 0 4px 8px rgba(0,0,0,0.15);
                }
                

                
                /* 仅为角色名片内的SVG图标添加优化,不影响游戏原生UI */
                .character-card .Icon_icon__2LtL_ {
                    width: 100%;
                    height: 100%;
                    filter: drop-shadow(0 0 2px rgba(0,0,0,0.3));
                    image-rendering: -webkit-optimize-contrast;
                    image-rendering: -moz-crisp-edges;
                    image-rendering: pixelated;
                }
                
                /* 空白技能槽样式 */
                .character-card .empty-skill-slot {
                    cursor: pointer;
                    border: 1px dashed rgba(74, 144, 226, 0.3);
                    background: transparent;
                    min-height: 70px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                }
                
                .character-card .empty-skill-slot:hover {
                    border: 1px dashed #4a90e2;
                    background: rgba(74, 144, 226, 0.1);
                }
                
                /* 技能选择器模态框样式 */
                .skill-selector-modal {
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    background: rgba(0, 0, 0, 0.8);
                    z-index: 20000;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    padding: 16px;
                    box-sizing: border-box;
                }
                
                .skill-selector-content {
                    background: #1a1a2e;
                    border-radius: 15px;
                    padding: 20px;
                    max-width: 80vw;
                    max-height: 80vh;
                    overflow: auto;
                    position: relative;
                    min-width: 400px;
                    border: 2px solid #4a90e2;
                }
                
                .skill-selector-header {
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    margin-bottom: 20px;
                    border-bottom: 1px solid #4a90e2;
                    padding-bottom: 10px;
                }
                
                .skill-selector-header h3 {
                    margin: 0;
                    color: #fff;
                    font-size: 18px;
                }
                
                .close-skill-selector {
                    background: none;
                    border: none;
                    font-size: 24px;
                    cursor: pointer;
                    color: #ccc;
                    padding: 0;
                    width: 30px;
                    height: 30px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                }
                
                .close-skill-selector:hover {
                    color: #fff;
                }
                
                .skill-selector-grid {
                    display: grid;
                    grid-template-columns: repeat(4, 1fr);
                    gap: 12px;
                    max-height: 400px;
                    overflow-y: auto;
                }
                
                .skill-option {
                    display: flex;
                    flex-direction: column;
                    align-items: center;
                    padding: 8px;
                    border: 1px solid #4a90e2;
                    border-radius: 8px;
                    cursor: pointer;
                    transition: all 0.2s ease;
                    background: rgba(255, 255, 255, 0.05);
                }
                
                .skill-option:hover {
                    border-color: #4a90e2;
                    background: rgba(74, 144, 226, 0.2);
                    transform: scale(1.05);
                }
                
                .skill-option-icon {
                    width: 40px;
                    height: 40px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    margin-bottom: 4px;
                }
                
                .skill-option-level {
                    font-size: 11px;
                    font-weight: bold;
                    color: #fff;
                    text-align: center;
                }
                
                /* 空技能选项样式 */
                .skill-option.empty-skill-option {
                    border: 1px dashed #4a90e2;
                    background: rgba(255, 255, 255, 0.02);
                }
                
                .skill-option.empty-skill-option:hover {
                    border-color: #4a90e2;
                    background: rgba(74, 144, 226, 0.1);
                }
                
                .empty-skill-icon {
                    width: 40px;
                    height: 40px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    border: 1px dashed #4a90e2;
                    border-radius: 4px;
                    color: #4a90e2;
                    font-size: 16px;
                    font-weight: bold;
                }
                

                
                /* 移动端技能选择器调整 */
                @media (max-width: 768px) {
                    .skill-selector-content {
                        max-width: 95vw;
                        min-width: 300px;
                        padding: 15px;
                    }
                    
                    .skill-selector-grid {
                        grid-template-columns: repeat(4, 1fr);
                        gap: 8px;
                    }
                    
                    .skill-option {
                        padding: 6px;
                    }
                    
                    .skill-option-icon {
                        width: 32px;
                        height: 32px;
                    }
                    
                    .skill-option-level {
                        font-size: 10px;
                    }
                    
                    .empty-skill-icon {
                        width: 32px;
                        height: 32px;
                        font-size: 14px;
                    }
                }
            `;
            document.head.appendChild(style);
        }

        async function readClipboardData() {
            try {
                const text = await navigator.clipboard.readText();
                return text;
            } catch (error) {
                console.log('无法读取剪贴板:', error);
                return null;
            }
        }

        function isValidCharacterData(data) {
            if (!data || typeof data !== 'object') return false;
            
            // 检查新格式 (player对象)
            if (data.player && (
                data.player.equipment || 
                data.player.characterItems || 
                data.player.staminaLevel !== undefined ||
                data.player.name
            )) {
                return true;
            }
            
            // 检查旧格式
            if (data.character && (data.characterSkills || data.characterItems)) {
                return true;
            }
            
            // 检查是否直接包含关键字段
            if (data.equipment || data.characterItems || data.characterSkills) {
                return true;
            }
            
            // 检查是否包含技能等级字段
            if (data.staminaLevel !== undefined || data.intelligenceLevel !== undefined || 
                data.attackLevel !== undefined || data.powerLevel !== undefined) {
                return true;
            }
            
            // 检查是否包含房屋数据
            if (data.houseRooms || data.characterHouseRoomMap) {
                return true;
            }
            
            // 检查是否包含能力数据
            if (data.abilities && Array.isArray(data.abilities)) {
                return true;
            }
            
            return false;
        }

        // 获取SVG sprite内容
        async function loadSpriteContent(spriteUrl) {
            try {
                const response = await fetch(spriteUrl);
                const svgText = await response.text();
                const parser = new DOMParser();
                const svgDoc = parser.parseFromString(svgText, 'image/svg+xml');
                return svgDoc.documentElement;
            } catch (error) {
                console.warn('无法加载sprite:', spriteUrl, error);
                return null;
            }
        }

        // 下载名片功能
        async function downloadCharacterCard() {
            try {
                // 获取名片元素
                const cardElement = document.getElementById('character-card');
                if (!cardElement) {
                    alert(isZH ? '未找到名片元素' : 'Character card element not found');
                    return;
                }

                // 显示下载提示
                const downloadBtn = document.querySelector('.download-card-btn');
                const originalText = downloadBtn.textContent;
                downloadBtn.textContent = isZH ? '生成中...' : 'Generating...';
                downloadBtn.disabled = true;

                // 克隆名片元素用于处理
                const clonedCard = cardElement.cloneNode(true);
                
                // 如果是场景2(我的角色名片),重新生成技能面板以保持自定义技能状态
                const isMyCharacterCard = cardElement.querySelector('.skill-panel .empty-skill-slot') !== null;
                if (isMyCharacterCard && state.customSkills.selectedSkills.length > 0) {
                    const skillPanel = clonedCard.querySelector('.skill-panel');
                    if (skillPanel) {
                        const characterData = {
                            abilities: window.characterCardWebSocketData?.characterAbilities || [],
                            characterSkills: window.characterCardWebSocketData?.characterSkills || []
                        };
                        const newSkillPanel = generateSkillPanel(characterData, true);
                        skillPanel.innerHTML = newSkillPanel.replace(/<div class="skill-panel">([\s\S]*?)<\/div>$/, '$1');
                    }
                }
                
                // 预加载所有sprite内容
                const spriteContents = {};
                const spriteUrls = Object.values(state.svgTool.spriteSheets);
                
                // 检查是否需要加载聊天图标sprite
                const needsChatSprite = clonedCard.querySelector('svg use[href*="chat_icons_sprite"]');
                if (needsChatSprite) {
                    spriteUrls.push('/static/media/chat_icons_sprite.2a8f0be2.svg');
                }
                
                for (const url of spriteUrls) {
                    const content = await loadSpriteContent(url);
                    if (content) {
                        spriteContents[url] = content;
                    }
                }



                // 替换所有使用<use>的SVG为实际内容
                const useElements = clonedCard.querySelectorAll('svg use');
                
                useElements.forEach((useElement, index) => {
                    try {
                        const href = useElement.getAttribute('href');
                        const svg = useElement.closest('svg');
                        
                        if (href && href.includes('#')) {
                            const [spriteUrl, symbolId] = href.split('#');
                            const spriteContent = spriteContents[spriteUrl];
                            
                            if (spriteContent && symbolId) {
                                const symbol = spriteContent.querySelector(`#${symbolId}`);
                                if (symbol) {
                                    // 创建新的SVG内容
                                    const svg = useElement.closest('svg');
                                    if (svg) {
                                        const symbolClone = symbol.cloneNode(true);
                                        
                                        // 清空原SVG内容并添加symbol内容
                                        svg.innerHTML = '';
                                        
                                        // 添加fill="none"属性解决填充问题
                                        svg.setAttribute('fill', 'none');
                                        
                                        // 如果symbol有viewBox,应用到svg
                                        const viewBox = symbol.getAttribute('viewBox');
                                        if (viewBox) {
                                            svg.setAttribute('viewBox', viewBox);
                                        }
                                        
                                        // 复制symbol的所有子元素到svg
                                        while (symbolClone.firstChild) {
                                            svg.appendChild(symbolClone.firstChild);
                                        }
                                    }
                                } else {
                                    // 如果找不到symbol,创建文字替代
                                    const svg = useElement.closest('svg');
                                    if (svg) {
                                        svg.innerHTML = `<text x="50%" y="50%" text-anchor="middle" dominant-baseline="middle" fill="white" font-size="10">${symbolId.substring(0, 3)}</text>`;
                                    }
                                }
                            } else {
                                // 如果找不到spriteContent,创建简单替代
                                const svg = useElement.closest('svg');
                                if (svg && symbolId) {
                                    const shortText = symbolId.length > 2 ? symbolId.substring(0, 2) : symbolId;
                                    svg.innerHTML = `<text x="50%" y="50%" text-anchor="middle" dominant-baseline="middle" fill="white" font-size="8">${shortText}</text>`;
                                }
                            }
                        }
                    } catch (error) {
                        console.warn('处理SVG元素时出错:', error);
                    }
                });
                
                // 简单处理角色名 - 移除上级div的class使其显示为白色
                const characterNameDiv = clonedCard.querySelector('.CharacterName_name__1amXp');
                if (characterNameDiv) {
                    characterNameDiv.className = ''; // 清除所有class,使角色名显示为白色
                }

                // 检测是否为移动端设备
                const isMobileDevice = isMobile();
                
                // 内联关键样式(避免linear-gradient问题)
                const styleElement = document.createElement('style');
                
                // 根据设备类型选择不同的样式
                if (isMobileDevice) {
                    // 移动端样式 - 单列布局
                    styleElement.textContent = `
                        .character-card {
                            background: #1a1a2e !important;
                            border: 2px solid #4a90e2 !important;
                            border-radius: 15px !important;
                            padding: 15px !important;
                            color: white !important;
                            font-family: Arial, sans-serif !important;
                            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5) !important;
                            max-width: 100% !important;
                            width: 350px !important;
                        }
                        .card-header {
                            text-align: center !important;
                            margin-bottom: 15px !important;
                            border-bottom: 2px solid #4a90e2 !important;
                            padding-bottom: 8px !important;
                        }
                        .card-content {
                            display: grid !important;
                            grid-template-columns: 1fr !important;
                            grid-template-rows: auto auto auto auto !important;
                            gap: 15px !important;
                        }
                        .equipment-panel { grid-column: 1 !important; grid-row: 1 !important; }
                        .ability-panel { grid-column: 1 !important; grid-row: 2 !important; }
                        .house-panel { grid-column: 1 !important; grid-row: 3 !important; }
                        .skill-panel { grid-column: 1 !important; grid-row: 4 !important; }
                        .equipment-panel, .house-panel, .ability-panel, .skill-panel {
                            background: rgba(255, 255, 255, 0.1) !important;
                            border-radius: 10px !important;
                            padding: 10px !important;
                            margin-bottom: 4px !important;
                            border: 1px solid rgba(74, 144, 226, 0.3) !important;
                        }
                        .panel-title {
                            margin: 0 0 10px 0 !important;
                            color: #4a90e2 !important;
                            font-size: 14px !important;
                            border-bottom: 1px solid rgba(74, 144, 226, 0.3) !important;
                            padding-bottom: 4px !important;
                            text-align: center !important;
                        }
                        .EquipmentPanel_playerModel__3LRB6 {
                            display: grid !important;
                            grid-template-columns: repeat(5, 1fr) !important;
                            grid-template-rows: repeat(4, auto) !important;
                            gap: 6px !important;
                            padding: 8px !important;
                            max-width: 100% !important;
                            margin: 0 auto !important;
                        }
                        /* 技能面板 - 每行4个 */
                        .ability-panel .AbilitiesPanel_abilityGrid__-p-VF {
                            display: grid !important;
                            grid-template-columns: repeat(4, 1fr) !important;
                            gap: 10px !important;
                            padding: 12px !important;
                            max-height: 180px !important;
                            overflow-y: auto !important;
                        }
                        
                        /* 房屋面板 - 每行4个 */
                        .house-panel .AbilitiesPanel_abilityGrid__-p-VF {
                            display: grid !important;
                            grid-template-columns: repeat(4, 1fr) !important;
                            gap: 8px !important;
                            padding: 10px !important;
                            max-height: 180px !important;
                            overflow-y: auto !important;
                        }
                        /* 技能卡片样式 */
                        .ability-panel .Ability_ability__1njrh {
                            margin: 2px !important;
                            min-height: 75px !important;
                        }
                        
                        /* 房屋卡片样式 - 4列布局 */
                        .house-panel .Ability_ability__1njrh {
                            margin: 1px !important;
                            min-height: 65px !important;
                            font-size: 11px !important;
                        }
                        .level { color: #fff !important; font-weight: bold !important; font-size: 12px !important; }
                        svg { width: 100% !important; height: 100% !important; }
                    `;
                } else {
                    // 桌面端样式 - 双列布局
                    styleElement.textContent = `
                        .character-card {
                            background: #1a1a2e !important;
                            border: 2px solid #4a90e2 !important;
                            border-radius: 15px !important;
                            padding: 20px !important;
                            color: white !important;
                            font-family: Arial, sans-serif !important;
                            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5) !important;
                        }
                        .card-header {
                            text-align: center !important;
                            margin-bottom: 20px !important;
                            border-bottom: 2px solid #4a90e2 !important;
                            padding-bottom: 10px !important;
                        }
                        .card-content {
                            display: grid !important;
                            grid-template-columns: 1fr 0.7fr !important;
                            grid-template-rows: auto 1fr !important;
                            gap: 20px !important;
                        }
                        .equipment-panel { grid-column: 1 !important; grid-row: 1 !important; }
                        .ability-panel { grid-column: 2 !important; grid-row: 1 !important; }
                        .house-panel { grid-column: 1 !important; grid-row: 2 !important; }
                        .skill-panel { grid-column: 2 !important; grid-row: 2 !important; }
                        .equipment-panel, .house-panel, .ability-panel, .skill-panel {
                            background: rgba(255, 255, 255, 0.1) !important;
                            border-radius: 10px !important;
                            padding: 15px !important;
                            border: 1px solid rgba(74, 144, 226, 0.3) !important;
                        }
                        .panel-title {
                            margin: 0 0 15px 0 !important;
                            color: #4a90e2 !important;
                            font-size: 16px !important;
                            border-bottom: 1px solid rgba(74, 144, 226, 0.3) !important;
                            padding-bottom: 5px !important;
                            text-align: center !important;
                        }
                        .EquipmentPanel_playerModel__3LRB6 {
                            display: grid !important;
                            grid-template-columns: repeat(5, 1fr) !important;
                            grid-template-rows: repeat(4, auto) !important;
                            gap: 8px !important;
                            padding: 10px !important;
                            max-width: 350px !important;
                            margin: 0 auto !important;
                        }
                        .AbilitiesPanel_abilityGrid__-p-VF {
                            display: grid !important;
                            grid-template-columns: repeat(4, 1fr) !important;
                            gap: 8px !important;
                            padding: 10px !important;
                            max-height: 180px !important;
                            overflow-y: auto !important;
                        }
                        .level { color: #fff !important; font-weight: bold !important; }
                        svg { width: 100% !important; height: 100% !important; }
                    `;
                }
                clonedCard.insertBefore(styleElement, clonedCard.firstChild);
                

                
                // 创建临时容器
                const tempContainer = document.createElement('div');
                tempContainer.style.position = 'absolute';
                tempContainer.style.left = '-9999px';
                tempContainer.style.top = '-9999px';
                tempContainer.appendChild(clonedCard);
                document.body.appendChild(tempContainer);

                // 配置html2canvas选项(根据设备类型调整)
                const options = {
                    backgroundColor: '#1a1a2e', // 使用纯色背景代替渐变
                    scale: isMobileDevice ? 1.5 : 2, // 移动端使用较小的缩放比例
                    useCORS: true,
                    allowTaint: true,
                    foreignObjectRendering: false,
                    width: isMobileDevice ? 350 : cardElement.offsetWidth, // 移动端使用固定宽度
                    height: isMobileDevice ? undefined : cardElement.offsetHeight, // 移动端自动计算高度
                    logging: false, // 关闭日志减少干扰
                    onclone: function(clonedDoc) {
                        try {
                            // 在克隆的文档中应用样式修复
                            const clonedCard = clonedDoc.querySelector('#character-card');
                            if (clonedCard) {
                                if (isMobileDevice) {
                                    // 移动端样式修复
                                    clonedCard.style.background = '#1a1a2e';
                                    clonedCard.style.border = '2px solid #4a90e2';
                                    clonedCard.style.borderRadius = '15px';
                                    clonedCard.style.padding = '15px';
                                    clonedCard.style.color = 'white';
                                    clonedCard.style.fontFamily = 'Arial, sans-serif';
                                    clonedCard.style.width = '350px';
                                    clonedCard.style.maxWidth = '100%';
                                } else {
                                    // 桌面端样式修复
                                    clonedCard.style.background = '#1a1a2e';
                                    clonedCard.style.border = '2px solid #4a90e2';
                                    clonedCard.style.borderRadius = '15px';
                                    clonedCard.style.padding = '20px';
                                    clonedCard.style.color = 'white';
                                    clonedCard.style.fontFamily = 'Arial, sans-serif';
                                }
                                
                                // 确保所有文本都是白色
                                const allText = clonedCard.querySelectorAll('*');
                                allText.forEach(el => {
                                    if (el.tagName !== 'SVG' && el.tagName !== 'USE') {
                                        el.style.color = 'white';
                                    }
                                });
                            }
                        } catch (error) {
                            console.warn('处理克隆文档时出错:', error);
                        }
                    }
                };

                // 生成画布
                const canvas = await html2canvas(clonedCard, options);
                
                // 清理临时容器
                document.body.removeChild(tempContainer);
                
                // 检查画布是否有内容
                const ctx = canvas.getContext('2d');
                const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                const data = imageData.data;
                let hasContent = false;
                
                // 检查是否有非透明像素
                for (let i = 3; i < data.length; i += 4) {
                    if (data[i] > 0) {
                        hasContent = true;
                        break;
                    }
                }
                
                if (!hasContent) {
                    console.warn('主要下载方法生成的图片为空,尝试备用方法...');
                    // 使用更简单的方法重试
                    const simpleOptions = {
                        backgroundColor: '#1a1a2e',
                        scale: 1,
                        useCORS: false,
                        allowTaint: true,
                        logging: false,
                        width: cardElement.offsetWidth,
                        height: cardElement.offsetHeight
                    };
                    
                    const simpleCanvas = await html2canvas(cardElement, simpleOptions);
                    const simpleCtx = simpleCanvas.getContext('2d');
                    const simpleImageData = simpleCtx.getImageData(0, 0, simpleCanvas.width, simpleCanvas.height);
                    const simpleData = simpleImageData.data;
                    let simpleHasContent = false;
                    
                    // 检查备用方法是否有内容
                    for (let i = 3; i < simpleData.length; i += 4) {
                        if (simpleData[i] > 0) {
                            simpleHasContent = true;
                            break;
                        }
                    }
                    
                    if (simpleHasContent) {
                        // 备用方法成功,使用备用画布
                        const link = document.createElement('a');
                        link.download = `MWI_Character_Card_${new Date().getTime()}.png`;
                        link.href = simpleCanvas.toDataURL('image/png', 1.0);
                        document.body.appendChild(link);
                        link.click();
                        document.body.removeChild(link);
                        
                        // 清理并恢复按钮状态
                        document.body.removeChild(tempContainer);
                        downloadBtn.textContent = originalText;
                        downloadBtn.disabled = false;
                        console.log('使用备用方法成功生成名片图片');
                        return;
                    } else {
                        throw new Error('生成的图片没有内容(主要方法和备用方法都失败)');
                    }
                }
                
                // 创建下载链接
                const link = document.createElement('a');
                link.download = `MWI_Character_Card_${new Date().getTime()}.png`;
                link.href = canvas.toDataURL('image/png', 1.0);
                
                // 触发下载
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);

                // 恢复按钮状态
                downloadBtn.textContent = originalText;
                downloadBtn.disabled = false;
                
                console.log('名片图片已生成并下载');
                
            } catch (error) {
                console.error('下载名片失败:', error);
                alert(isZH ? 
                    '下载名片失败\n\n错误信息: ' + error.message + '\n\n建议:请确保网络连接正常,并允许浏览器下载文件' : 
                    'Failed to download character card\n\nError: ' + error.message + '\n\nSuggestion: Please ensure network connection and allow browser downloads');
                
                // 恢复按钮状态
                const downloadBtn = document.querySelector('.download-card-btn');
                if (downloadBtn) {
                    downloadBtn.textContent = isZH ? '下载名片(Beta)' : 'Download Card(Beta)';
                    downloadBtn.disabled = false;
                }
            }
        }



        // 自动点击导出按钮的辅助函数
        async function autoClickExportButton() {
            try {
                console.log('尝试自动点击导出按钮...');
                
                // 查找导出按钮的多种可能选择器
                const exportButtonSelectors = [
                    // 中文版本的按钮文本
                    'button:contains("导出人物到剪贴板")',
                    // 英文版本的按钮文本
                    'button:contains("Export to clipboard")',
                ];
                
                let exportButton = null;
                
                // 尝试通过按钮文本查找(中文和英文)
                const allButtons = document.querySelectorAll('button');
                for (const button of allButtons) {
                    const buttonText = button.textContent.trim();
                    if (buttonText.includes('导出人物到剪贴板') || 
                        buttonText.includes('Export to clipboard')) {
                        exportButton = button;
                        break;
                    }
                }
                
                // 如果通过文本没找到,尝试其他属性
                if (!exportButton) {
                    for (const selector of exportButtonSelectors.slice(4)) { // 跳过contains选择器
                        try {
                            exportButton = document.querySelector(selector);
                            if (exportButton) {
                                console.log('通过选择器找到导出按钮:', selector);
                                break;
                            }
                        } catch (e) {
                            // 忽略选择器错误
                        }
                    }
                }
                
                if (!exportButton) {
                    console.log('未找到导出按钮,将直接尝试读取剪贴板');
                    return false;
                }
                
                // 检查按钮是否可点击
                if (exportButton.disabled || exportButton.style.display === 'none') {
                    console.log('导出按钮不可用,将直接尝试读取剪贴板');
                    return false;
                }
                
                // 点击按钮
                exportButton.click();
                console.log('已点击导出按钮,等待数据导出...');
                
                // 等待一段时间让数据导出到剪贴板
                await new Promise(resolve => setTimeout(resolve, 500));
                
                return true;
            } catch (error) {
                console.log('自动点击导出按钮失败:', error);
                return false;
            }
        }

        // 使用剪贴板数据生成名片(用于查看其他角色)
        async function showCharacterCard() {
            try {
                let characterData = null;
                let dataSource = "剪贴板数据";
                
                // 先尝试自动点击导出按钮
                const autoExportSuccess = await autoClickExportButton();
                
                const clipboardText = await readClipboardData();
                
                if (!clipboardText) {
                    const errorMessage = autoExportSuccess ? 
                        (isZH ? 
                            '已尝试自动导出,但无法读取剪贴板数据\n\n请确保:\n1. 允许浏览器访问剪贴板\n2. 等待导出完成后重试' :
                            'Auto export attempted, but cannot read clipboard data\n\nPlease ensure:\n1. Allow browser to access clipboard\n2. Wait for export to complete and retry'
                        ) : 
                        (isZH ? 
                            '无法读取剪贴板数据\n\n请确保:\n1. 先点击"导出人物到剪贴板"按钮\n2. 允许浏览器访问剪贴板\n3. 剪贴板中有有效的角色数据' : 
                            'Cannot read clipboard data\n\nPlease ensure:\n1. Click "Export to clipboard" button first\n2. Allow browser to access clipboard\n3. Valid character data in clipboard'
                        );
                    alert(errorMessage);
                    return;
                }
                
                try {
                    characterData = JSON.parse(clipboardText);
                } catch (error) {
                    alert(isZH ? 
                        '剪贴板中的数据不是有效的JSON格式\n\n请确保先点击"导出人物到剪贴板"按钮' : 
                        'Data in clipboard is not valid JSON\n\nPlease ensure you clicked "Export to clipboard" button first');
                    return;
                }
                
                if (!isValidCharacterData(characterData)) {
                    alert(isZH ? 
                        '剪贴板中的数据不包含有效的角色信息\n\n请确保使用MWI Tools的"导出人物到剪贴板"功能' : 
                        'Data in clipboard does not contain valid character information\n\nPlease ensure you use MWI Tools "Export to clipboard" feature');
                    return;
                }
                
                // 重置调试信息
                state.debugInfo.firstSvgPath = null;
                state.debugInfo.iconCount = 0;
                
                const characterName = characterData.player?.name || characterData.character?.name || (isZH ? '角色' : 'Character');
                
                // 查找页面中的角色信息元素 - 获取最后一个(用于查看其他角色)
                let characterNameElement = null;
                const characterNameDivs = document.querySelectorAll('.CharacterName_characterName__2FqyZ');
                if (characterNameDivs.length > 0) {
                    // 取最后一个元素(用于查看其他角色)
                    const lastCharacterNameDiv = characterNameDivs[characterNameDivs.length - 1];
                    characterNameElement = lastCharacterNameDiv.outerHTML;
                }
                
                const modal = document.createElement('div');
                modal.className = 'character-card-modal';
                modal.innerHTML = `
                    <div class="modal-content">
                        <button class="close-modal">&times;</button>
                        <div class="instruction-banner">
                            ${isZH ? 
                                `MWI角色名片插件 v${VERSION} (数据来源: ${dataSource})` :
                                `MWI Character Card Plugin v${VERSION} (Data Source: ${dataSource})`
                            }
                        </div>
                        <div class="download-section">
                            <button class="download-card-btn">${isZH ? '下载名片(Beta)' : 'Download Card(Beta)'}</button>
                        </div>
                        ${generateCharacterCard(characterData, characterName, characterNameElement, false)}
                    </div>
                `;

                modal.querySelector('.close-modal').onclick = () => document.body.removeChild(modal);
                modal.querySelector('.download-card-btn').onclick = downloadCharacterCard;
                modal.onclick = (e) => { if (e.target === modal) document.body.removeChild(modal); };
                
                // 添加技能槽点击事件监听器(仅场景2需要)
                const skillSlots = modal.querySelectorAll('.skill-slot, .empty-skill-slot');
                skillSlots.forEach(slot => {
                    slot.addEventListener('click', function() {
                        const skillIndex = parseInt(this.getAttribute('data-skill-index'));
                        showSkillSelector(skillIndex);
                    });
                });
                
                document.body.appendChild(modal);
                
            } catch (error) {
                console.error('生成角色名片失败:', error);
                alert(isZH ? 
                    '生成角色名片时发生错误\n\n错误信息: ' + error.message : 
                    'Error occurred while generating character card\n\nError: ' + error.message);
            }
        }

        // 使用WebSocket数据生成名片(用于查看当前角色)
        async function showMyCharacterCard() {
            try {
                // 获取当前角色名
                const currentCharacterName = window.characterCardWebSocketData?.characterName || 
                    window.characterCardWebSocketData?.name || 
                    (isZH ? '角色' : 'Character');
                
                // 检查是否需要重置技能配置(角色切换)
                const configKey = `mwi_skill_config_${currentCharacterName}`;
                const savedConfig = localStorage.getItem(configKey);
                
                if (savedConfig) {
                    // 有保存的配置,检查是否匹配当前角色
                    try {
                        const configData = JSON.parse(savedConfig);
                        if (configData.characterName === currentCharacterName) {
                            // 角色匹配,保持现有配置
                            console.log(`使用保存的技能配置: ${currentCharacterName}`);
                        } else {
                            // 角色不匹配,重置配置
                            state.customSkills.selectedSkills = [];
                            console.log(`角色切换,重置技能配置: ${currentCharacterName}`);
                        }
                    } catch (error) {
                        // 配置数据错误,重置
                        state.customSkills.selectedSkills = [];
                        console.log('配置数据错误,重置技能配置');
                    }
                } else {
                    // 没有保存的配置,重置
                    state.customSkills.selectedSkills = [];
                }
                
                let characterData = null;
                let dataSource = "WS数据";
                
                // 检查是否有WebSocket数据
                if (!window.characterCardWebSocketData) {
                    alert(isZH ? 
                        '未找到当前角色数据\n\n请确保:\n1. 已登录游戏\n2. 等待游戏数据加载完成\n3. 刷新页面后重试' : 
                        'No current character data found\n\nPlease ensure:\n1. You are logged into the game\n2. Wait for game data to load\n3. Refresh the page and try again');
                    return;
                }
                
                const parsedData = window.characterCardWebSocketData;
                
                if (parsedData && parsedData.type === "init_character_data") {
                    // 将WebSocket数据格式转换为角色名片插件需要的格式
                    characterData = {
                        player: {
                            name: parsedData.characterName || parsedData.name || (isZH ? '角色' : 'Character'),
                            equipment: parsedData.characterItems || [],
                            characterItems: parsedData.characterItems || [],
                            staminaLevel: parsedData.characterSkills?.find(s => s.skillHrid.includes('/skills/stamina'))?.level || 0,
                            intelligenceLevel: parsedData.characterSkills?.find(s => s.skillHrid.includes('/skills/intelligence'))?.level || 0,
                            attackLevel: parsedData.characterSkills?.find(s => s.skillHrid.includes('/skills/attack'))?.level || 0,
                            powerLevel: parsedData.characterSkills?.find(s => s.skillHrid.includes('/skills/power'))?.level || 0,
                            defenseLevel: parsedData.characterSkills?.find(s => s.skillHrid.includes('/skills/defense'))?.level || 0,
                            rangedLevel: parsedData.characterSkills?.find(s => s.skillHrid.includes('/skills/ranged'))?.level || 0,
                            magicLevel: parsedData.characterSkills?.find(s => s.skillHrid.includes('/skills/magic'))?.level || 0
                        },
                        abilities: parsedData.characterAbilities || [],
                        characterSkills: parsedData.characterSkills || [],
                        houseRooms: parsedData.characterHouseRoomMap || {},
                        characterHouseRoomMap: parsedData.characterHouseRoomMap || {}
                    };
                } else {
                    alert(isZH ? 
                        'WebSocket数据格式不正确\n\n请刷新页面后重试' : 
                        'WebSocket data format is incorrect\n\nPlease refresh the page and try again');
                    return;
                }
                
                if (!isValidCharacterData(characterData)) {
                    alert(isZH ? 
                        'WebSocket数据不包含有效的角色信息\n\n请刷新页面后重试' : 
                        'WebSocket data does not contain valid character information\n\nPlease refresh the page and try again');
                    return;
                }
                
                // 重置调试信息
                state.debugInfo.firstSvgPath = null;
                state.debugInfo.iconCount = 0;
                
                const characterName = characterData.player?.name || characterData.character?.name || (isZH ? '角色' : 'Character');
                
                // 查找页面中的角色信息元素 - 获取第一个(右上角的当前用户)
                let characterNameElement = null;
                const characterNameDivs = document.querySelectorAll('.CharacterName_characterName__2FqyZ');
                if (characterNameDivs.length > 0) {
                    // 取第一个元素(右上角的当前用户)
                    const firstCharacterNameDiv = characterNameDivs[0];
                    characterNameElement = firstCharacterNameDiv.outerHTML;
                }
                
                const modal = document.createElement('div');
                modal.className = 'character-card-modal';
                modal.innerHTML = `
                    <div class="modal-content">
                        <button class="close-modal">&times;</button>
                        <div class="instruction-banner">
                            ${isZH ? 
                                `MWI角色名片插件 v${VERSION} (数据来源: ${dataSource})` :
                                `MWI Character Card Plugin v${VERSION} (Data Source: ${dataSource})`
                            }
                        </div>
                        <div class="download-section">
                            <div class="button-row">
                                <button class="download-card-btn">${isZH ? '下载名片(Beta)' : 'Download Card(Beta)'}</button>
                                <button class="save-skill-config-btn">${isZH ? '保存技能配置' : 'Save Skill Config'}</button>
                                <button class="load-skill-config-btn">${isZH ? '读取技能配置' : 'Load Skill Config'}</button>
                            </div>
                            <div class="skill-hint">
                                <span>${isZH ? '💡 点击技能图标可更换/添加展示的技能' : '💡 Click skill icons to change/add displayed skills'}</span>
                            </div>
                        </div>
                        ${generateCharacterCard(characterData, characterName, characterNameElement, true)}
                    </div>
                `;

                modal.querySelector('.close-modal').onclick = () => document.body.removeChild(modal);
                modal.querySelector('.download-card-btn').onclick = downloadCharacterCard;
                modal.onclick = (e) => { if (e.target === modal) document.body.removeChild(modal); };
                
                // 添加技能配置按钮事件监听器
                modal.querySelector('.save-skill-config-btn').onclick = () => {
                    saveSkillConfig(characterName);
                };
                modal.querySelector('.load-skill-config-btn').onclick = () => {
                    loadSkillConfig(characterName);
                };
                
                // 添加技能槽点击事件监听器
                const skillSlots = modal.querySelectorAll('.skill-slot, .empty-skill-slot');
                skillSlots.forEach(slot => {
                    slot.addEventListener('click', function() {
                        const skillIndex = parseInt(this.getAttribute('data-skill-index'));
                        showSkillSelector(skillIndex);
                    });
                });
                
                document.body.appendChild(modal);
                
            } catch (error) {
                console.error('生成我的角色名片失败:', error);
                alert(isZH ? 
                    '生成我的角色名片时发生错误\n\n错误信息: ' + error.message : 
                    'Error occurred while generating my character card\n\nError: ' + error.message);
            }
        }

        function addCharacterCardButton() {
            const checkElem = () => {
                const selectedElement = document.querySelector(`div.SharableProfile_overviewTab__W4dCV`);
                if (selectedElement) {
                    clearInterval(state.timer);
                    if (selectedElement.querySelector('.character-card-btn')) return;

                    const button = document.createElement("button");
                    button.className = 'character-card-btn';
                    button.textContent = isZH ? "查看角色名片" : "View Character Card";
                    button.style.cssText = `
                        border-radius: 6px; height: 24px; background-color: #17a2b8; color: white;
                        box-shadow: 0 2px 4px rgba(0,0,0,0.1); border: 0px; margin: 10px auto; 
                        display: inline-block; padding: 0 16px; min-width: 140px; max-width: 180px;
                        font-size: 13px; cursor: pointer; transition: all 0.2s ease;
                    `;
                    
                    // 添加hover效果
                    button.addEventListener('mouseenter', () => {
                        button.style.backgroundColor = '#138496';
                        button.style.transform = 'translateY(-1px)';
                    });
                    
                    button.addEventListener('mouseleave', () => {
                        button.style.backgroundColor = '#17a2b8';
                        button.style.transform = 'translateY(0)';
                    });
                    
                    button.onclick = () => { 
                        showCharacterCard(); 
                        return false; 
                    };
                    
                    // 创建按钮容器并居中
                    const buttonContainer = document.createElement('div');
                    buttonContainer.style.cssText = 'text-align: center; margin-top: 10px;';
                    buttonContainer.appendChild(button);
                    
                    // 插入按钮容器
                    selectedElement.appendChild(buttonContainer);
                    
                    console.log('角色名片按钮已添加');
                    return false;
                }
            };
            state.timer = setInterval(checkElem, 1000);
        }

        // 在右上角角色信息区域添加"我的角色名片"按钮
        function addMyCharacterCardButton() {
            const checkMyButton = () => {
                const headerNameElements = document.querySelectorAll('.Header_name__227rJ');
                if (headerNameElements.length > 0) {
                    // 找到右上角的角色信息容器
                    const headerNameElement = headerNameElements[0];
                    
                    // 检查是否已经添加过按钮
                    if (headerNameElement.querySelector('.my-character-card-btn')) {
                        return;
                    }
                    
                    // 创建按钮
                    const myButton = document.createElement("button");
                    myButton.className = 'my-character-card-btn';
                    myButton.textContent = isZH ? "我的角色名片" : "My Character Card";
                    myButton.style.cssText = `
                        border-radius: 4px; height: 20px; background-color: #28a745; color: white;
                        box-shadow: 0 1px 3px rgba(0,0,0,0.2); border: 0px; margin-left: 8px;
                        display: inline-block; padding: 0 8px; font-size: 11px; cursor: pointer; 
                        transition: all 0.2s ease; vertical-align: middle;
                    `;
                    
                    // 添加hover效果
                    myButton.addEventListener('mouseenter', () => {
                        myButton.style.backgroundColor = '#218838';
                        myButton.style.transform = 'translateY(-1px)';
                    });
                    
                    myButton.addEventListener('mouseleave', () => {
                        myButton.style.backgroundColor = '#28a745';
                        myButton.style.transform = 'translateY(0)';
                    });
                    
                    myButton.onclick = () => { 
                        showMyCharacterCard(); 
                        return false; 
                    };
                    
                    // 将按钮插入到Header_name容器中
                    headerNameElement.appendChild(myButton);
                    
                    console.log('我的角色名片按钮已添加到右上角');
                    return false;
                }
            };
            
            // 使用定时器检查并添加按钮
            const myButtonTimer = setInterval(checkMyButton, 1000);
            
            // 清理定时器(当按钮添加成功后)
            setTimeout(() => {
                clearInterval(myButtonTimer);
            }, 10000); // 10秒后停止检查
        }

                 async function init() {
             console.log(`MWI角色名片插件 v${VERSION}`);
            console.log('使用说明:');
            console.log('1. 在角色信息界面点击"查看角色名片"按钮 - 使用剪贴板数据');
            console.log('2. 在右上角点击"我的角色名片"按钮 - 使用WebSocket数据');
            console.log('3. 下载选项:');
            console.log('   • "下载名片(Beta)" - 自动转换为PNG图片下载');
            console.log('4. 调试工具:');
            console.log('   • 安装 websocket_debug.js 查看WebSocket通信');
            console.log('   • 安装 test_data_sharing.js 测试数据共享');
            
            createModalStyles();
            const spritesLoaded = await state.svgTool.loadSpriteSheets();
            console.log(`图标系统初始化${spritesLoaded ? '成功' : '失败'},将使用${spritesLoaded ? 'MWI原版SVG图标' : '后备图标显示'}`);
            if (spritesLoaded) {
                console.log('SVG Sprite文件:', state.svgTool.spriteSheets);
            }
            
            // 设置WebSocket Hook
            hookWebSocket();
            
            // 监听角色数据可用事件
            window.addEventListener('characterDataAvailable', function(event) {
                // 静默处理事件
            });
            
            addCharacterCardButton();
            addMyCharacterCardButton();
            
            // 创建一个MutationObserver来监听body的子节点变化
            state.observer = new MutationObserver((mutationsList, observer) => {
                for(const mutation of mutationsList) {
                    if (mutation.type === 'childList') {
                        // 检查是否是SharableProfile_overviewTab__W4dCV的子节点变化
                        if (mutation.target.classList.contains('SharableProfile_overviewTab__W4dCV')) {
                            // 延迟执行,确保DOM更新完成
                            setTimeout(addCharacterCardButton, 100);
                        }
                    }
                }
            });
            state.observer.observe(document.body, { childList: true, subtree: true });
        }

        // 清理函数
        function cleanup() {
            if (state.observer) {
                state.observer.disconnect();
                state.observer = null;
            }
            if (state.timer) {
                clearInterval(state.timer);
                state.timer = null;
            }
        }

        // 暴露数据给其他脚本的函数
        function exposeDataToOtherScripts() {
            // 创建一个全局函数,让MWI Tools可以调用
            window.exposeMWIToolsData = function(data) {
                window.mwiToolsData = data;
            };
            
            // 监听来自MWI Tools的消息
            window.addEventListener('message', function(event) {
                if (event.source === window && event.data && event.data.type === 'MWI_TOOLS_DATA') {
                    window.mwiToolsData = event.data.data;
                }
            });
            
            // 监听localStorage变化
            window.addEventListener('storage', function(event) {
                if (event.key === 'init_character_data' && event.newValue) {
                    try {
                        const data = JSON.parse(event.newValue);
                        window.mwiToolsData = data;
                    } catch (error) {
                        // 静默处理错误
                    }
                }
            });
        }

        // WebSocket Hook函数 - 参考MWI Tools的实现
        function hookWebSocket() {
            // 检查是否已经hook过
            if (window.characterCardWebSocketHooked) {
                return;
            }
            
            try {
                // 获取MessageEvent.prototype.data的属性描述符
                const dataProperty = Object.getOwnPropertyDescriptor(MessageEvent.prototype, "data");
                if (!dataProperty) {
                    return;
                }
                
                const oriGet = dataProperty.get;
                
                // 重写getter
                dataProperty.get = function() {
                    const socket = this.currentTarget;
                    
                    // 检查是否是WebSocket连接
                    if (!(socket instanceof WebSocket)) {
                        return oriGet.call(this);
                    }
                    
                    // 检查是否是MWI的WebSocket连接
                    if (socket.url.indexOf("api.milkywayidle.com/ws") <= -1 && 
                        socket.url.indexOf("api-test.milkywayidle.com/ws") <= -1) {
                        return oriGet.call(this);
                    }
                    
                    // 获取原始消息
                    const message = oriGet.call(this);
                    
                    // 防止循环调用
                    Object.defineProperty(this, "data", { value: message });
                    
                    // 处理消息
                    handleWebSocketMessage(message);
                    
                    return message;
                };
                
                // 重新定义属性
                Object.defineProperty(MessageEvent.prototype, "data", dataProperty);
                
                // 标记已hook
                window.characterCardWebSocketHooked = true;
                
            } catch (error) {
                // 静默处理错误
            }
        }
        
        // 处理WebSocket消息
        function handleWebSocketMessage(message) {
            try {
                const obj = JSON.parse(message);
                
                // 处理角色数据
                if (obj && obj.type === "init_character_data") {
                    console.log('=== 检测到角色数据 ===');
                    console.log('角色名称:', obj.characterName);
                    console.log('装备数量:', obj.characterItems?.length || 0);
                    console.log('技能数量:', obj.characterSkills?.length || 0);
                    console.log('能力数量:', obj.characterAbilities?.length || 0);
                    console.log('房屋数据:', obj.characterHouseRoomMap);
                    console.log('完整数据:', obj);
                    
                    // 存储到全局变量
                    window.mwiToolsData = obj;
                    window.characterCardWebSocketData = obj;
                    
                    // 存储到localStorage
                    try {
                        localStorage.setItem('init_character_data', message);
                        console.log('已存储到localStorage');
                    } catch (error) {
                        console.log('localStorage存储失败:', error);
                    }
                    
                    // 触发数据可用事件
                    window.dispatchEvent(new CustomEvent('characterDataAvailable', {
                        detail: obj
                    }));
                    
                    console.log('=== 角色数据处理完成 ===');
                }
                
            } catch (error) {
                // 静默处理解析错误,不打印日志
            }
        }

        // 在脚本卸载时清理
        window.addEventListener('unload', cleanup);

        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', init);
        } else {
            init();
        }
        
        // 初始化数据暴露机制
        exposeDataToOtherScripts();
        
        // 保存技能配置函数
        function saveSkillConfig(characterName) {
            try {
                const configKey = `mwi_skill_config_${characterName}`;
                
                // 只保存技能ID和位置,不保存等级
                const simplifiedSkills = state.customSkills.selectedSkills.map((skill, index) => ({
                    abilityHrid: skill.abilityHrid,
                    position: index
                }));
                
                const configData = {
                    characterName: characterName,
                    selectedSkills: simplifiedSkills,
                    timestamp: Date.now()
                };
                
                localStorage.setItem(configKey, JSON.stringify(configData));
                
                // 显示成功提示
                const saveBtn = document.querySelector('.save-skill-config-btn');
                const originalText = saveBtn.textContent;
                saveBtn.textContent = isZH ? '保存成功!' : 'Saved!';
                saveBtn.style.backgroundColor = '#28a745';
                
                setTimeout(() => {
                    saveBtn.textContent = originalText;
                    saveBtn.style.backgroundColor = '#17a2b8';
                }, 2000);
                
                console.log(`技能配置已保存: ${characterName}`);
            } catch (error) {
                console.error('保存技能配置失败:', error);
                alert(isZH ? '保存技能配置失败' : 'Failed to save skill config');
            }
        }
        
        // 读取技能配置函数
        function loadSkillConfig(characterName) {
            try {
                const configKey = `mwi_skill_config_${characterName}`;
                const savedConfig = localStorage.getItem(configKey);
                
                if (!savedConfig) {
                    alert(isZH ? 
                        `未找到角色 "${characterName}" 的技能配置\n\n请先保存技能配置` : 
                        `No skill config found for character "${characterName}"\n\nPlease save skill config first`);
                    return false;
                }
                
                const configData = JSON.parse(savedConfig);
                
                // 验证配置数据
                if (!configData.selectedSkills || !Array.isArray(configData.selectedSkills)) {
                    alert(isZH ? '技能配置数据格式错误' : 'Invalid skill config data format');
                    return false;
                }
                
                // 从WebSocket数据获取最新技能信息并应用配置
                const allSkills = window.characterCardWebSocketData?.characterAbilities || [];
                const restoredSkills = [];
                
                configData.selectedSkills.forEach(savedSkill => {
                    if (savedSkill.abilityHrid) {
                        // 从WebSocket数据中找到对应的技能
                        const currentSkill = allSkills.find(skill => 
                            skill.abilityHrid === savedSkill.abilityHrid
                        );
                        
                        if (currentSkill) {
                            // 使用最新的等级信息
                            restoredSkills[savedSkill.position] = {
                                abilityHrid: currentSkill.abilityHrid,
                                level: currentSkill.level,
                                slotNumber: currentSkill.slotNumber
                            };
                        }
                    }
                });
                
                // 应用恢复的技能配置
                state.customSkills.selectedSkills = restoredSkills;
                
                // 重新生成技能面板
                const characterCard = document.querySelector('#character-card');
                if (characterCard) {
                    const skillPanel = characterCard.querySelector('.skill-panel');
                    if (skillPanel) {
                        const characterData = {
                            abilities: window.characterCardWebSocketData?.characterAbilities || [],
                            characterSkills: window.characterCardWebSocketData?.characterSkills || []
                        };
                        const newSkillPanel = generateSkillPanel(characterData, true);
                        skillPanel.innerHTML = newSkillPanel.replace(/<div class="skill-panel">([\s\S]*?)<\/div>$/, '$1');
                        
                        // 重新添加事件监听器
                        const skillSlots = skillPanel.querySelectorAll('.skill-slot, .empty-skill-slot');
                        skillSlots.forEach(slot => {
                            slot.addEventListener('click', function() {
                                const skillIndex = parseInt(this.getAttribute('data-skill-index'));
                                showSkillSelector(skillIndex);
                            });
                        });
                    }
                }
                
                // 显示成功提示
                const loadBtn = document.querySelector('.load-skill-config-btn');
                const originalText = loadBtn.textContent;
                loadBtn.textContent = isZH ? '读取成功!' : 'Loaded!';
                loadBtn.style.backgroundColor = '#28a745';
                
                setTimeout(() => {
                    loadBtn.textContent = originalText;
                    loadBtn.style.backgroundColor = '#17a2b8';
                }, 2000);
                
                console.log(`技能配置已读取: ${characterName}`);
                return true;
            } catch (error) {
                console.error('读取技能配置失败:', error);
                alert(isZH ? '读取技能配置失败' : 'Failed to load skill config');
                return false;
            }
        }
        
        // 将函数暴露到全局作用域
        if (typeof window !== 'undefined') {
            window.showSkillSelector = showSkillSelector;
            window.selectSkill = selectSkill;
        }

    })(); // 结束立即执行函数

})();