猫猫放置强化助手

强化自动化工具

目前為 2025-06-21 提交的版本,檢視 最新版本

// ==UserScript==
// @name         猫猫放置强化助手
// @version      v3.1
// @description  强化自动化工具
// @author       YuoHira
// @license      MIT
// @match        https://www.moyu-idle.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=moyu-idle.com
// @grant        none
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/pako.min.js
// @namespace https://gf.qytechs.cn/users/397156
// ==/UserScript==

(function() {
  'use strict';

  // —— 默认配置 ——
  let TARGET_LEVEL = 5;           // 目标强化等级
  let ENHANCE_INTERVAL = 1000;    // 强化间隔(毫秒)
  let isAutoEnhancing = false;    // 自动强化状态
  let enhanceTimer = null;        // 强化定时器
  let storedEnhanceData = null;   // 储存的强化数据(完整的请求对象)
  let currentEnhanceItem = null;  // 当前强化物品信息
  let DEBUG_MODE = false;         // 调试模式(默认关闭)
  let PROTECT_START_LEVEL = 3;    // 从几级开始使用保护材料
  let BATCH_COUNT = 1;            // 批量强化次数
  let currentBatchCount = 0;      // 当前剩余强化次数

  let waitingForResult = false;   // 等待强化结果
  
  // —— 强化统计数据 ——
  let enhanceStats = {
      baseItem: '',               // 基础物品名称
      currentLevel: 0,            // 当前等级
      targetLevel: 0,             // 目标等级
      maxReachedLevel: 0,         // 历史最大等级
      levelStats: {},             // 每级统计 {level: {attempts: 0, success: 0}}
      totalAttempts: 0,           // 总尝试次数
      totalSuccess: 0,            // 总成功次数
      startTime: null             // 开始时间
  };
  
  // —— 本地存储键名 ——
  const STORAGE_KEYS = {
      POSITION: 'enhanceHelper_position',
      TARGET_LEVEL: 'enhanceHelper_targetLevel',
      INTERVAL: 'enhanceHelper_interval',
      CURRENT_ITEM: 'enhanceHelper_currentItem',
      STORED_REQUEST: 'enhanceHelper_storedRequest',
      DEBUG_MODE: 'enhanceHelper_debugMode',
      PROTECT_START_LEVEL: 'enhanceHelper_protectStartLevel',
      IS_MINIMIZED: 'enhanceHelper_isMinimized',
      BATCH_COUNT: 'enhanceHelper_batchCount',
      CURRENT_BATCH_COUNT: 'enhanceHelper_currentBatchCount'
  };
  
  // —— 界面状态 ——
  let isMinimized = false;
  
  // —— 加载本地配置 ——
  function loadConfig() {
      const savedTarget = localStorage.getItem(STORAGE_KEYS.TARGET_LEVEL);
      const savedInterval = localStorage.getItem(STORAGE_KEYS.INTERVAL);
      const savedCurrentItem = localStorage.getItem(STORAGE_KEYS.CURRENT_ITEM);
      const savedStoredRequest = localStorage.getItem(STORAGE_KEYS.STORED_REQUEST);
      const savedDebugMode = localStorage.getItem(STORAGE_KEYS.DEBUG_MODE);
      
      const savedProtectStartLevel = localStorage.getItem(STORAGE_KEYS.PROTECT_START_LEVEL);
      const savedIsMinimized = localStorage.getItem(STORAGE_KEYS.IS_MINIMIZED);
      const savedBatchCount = localStorage.getItem(STORAGE_KEYS.BATCH_COUNT);
      const savedCurrentBatchCount = localStorage.getItem(STORAGE_KEYS.CURRENT_BATCH_COUNT);
      
      if (savedTarget) TARGET_LEVEL = parseInt(savedTarget, 10);
      if (savedInterval) ENHANCE_INTERVAL = parseInt(savedInterval, 10);
      if (savedDebugMode) DEBUG_MODE = savedDebugMode === 'true';
      if (savedProtectStartLevel) PROTECT_START_LEVEL = parseInt(savedProtectStartLevel, 10);
      if (savedIsMinimized) isMinimized = savedIsMinimized === 'true';
      if (savedBatchCount) BATCH_COUNT = parseInt(savedBatchCount, 10);
      if (savedCurrentBatchCount) currentBatchCount = parseInt(savedCurrentBatchCount, 10);
      
      // 恢复当前强化物品
      if (savedCurrentItem) {
          try {
              currentEnhanceItem = JSON.parse(savedCurrentItem);
          } catch (e) {
              currentEnhanceItem = null;
          }
      }
      
      // 恢复储存的请求数据
      if (savedStoredRequest) {
          try {
              storedEnhanceData = JSON.parse(savedStoredRequest);
          } catch (e) {
              storedEnhanceData = null;
          }
      }
  }
  
  // —— 保存配置 ——
  function saveConfig() {
      localStorage.setItem(STORAGE_KEYS.TARGET_LEVEL, TARGET_LEVEL);
      localStorage.setItem(STORAGE_KEYS.INTERVAL, ENHANCE_INTERVAL);
      localStorage.setItem(STORAGE_KEYS.DEBUG_MODE, DEBUG_MODE);
      localStorage.setItem(STORAGE_KEYS.PROTECT_START_LEVEL, PROTECT_START_LEVEL);
      localStorage.setItem(STORAGE_KEYS.IS_MINIMIZED, isMinimized);
      localStorage.setItem(STORAGE_KEYS.BATCH_COUNT, BATCH_COUNT);
      localStorage.setItem(STORAGE_KEYS.CURRENT_BATCH_COUNT, currentBatchCount);
  }
  
  // —— 保存当前强化物品 ——
  function saveCurrentItem() {
      if (currentEnhanceItem) {
          localStorage.setItem(STORAGE_KEYS.CURRENT_ITEM, JSON.stringify(currentEnhanceItem));
      } else {
          localStorage.removeItem(STORAGE_KEYS.CURRENT_ITEM);
      }
  }
  
  // —— 保存强化请求数据 ——
  function saveStoredRequest() {
      if (storedEnhanceData) {
          localStorage.setItem(STORAGE_KEYS.STORED_REQUEST, JSON.stringify(storedEnhanceData));
      } else {
          localStorage.removeItem(STORAGE_KEYS.STORED_REQUEST);
      }
  }
  
  // —— 边界检查函数 ——
  function constrainPosition(x, y, panelWidth = 480, panelHeight = 400) {
      const windowWidth = window.innerWidth;
      const windowHeight = window.innerHeight;
      
      // 确保面板至少有50px在可见范围内
      const minVisible = 50;
      
      // 检查右边界(x是right值)
      if (x < 0) {
          x = 20; // 默认右边距
      } else if (x > windowWidth - minVisible) {
          x = windowWidth - minVisible;
      }
      
      // 检查上下边界(y是top值)  
      if (y < 0) {
          y = 20; // 默认上边距
      } else if (y > windowHeight - minVisible) {
          y = windowHeight - minVisible;
      }
      
      return {x, y};
  }
  
  // —— 保存位置 ——
  function savePosition(x, y) {
      const constrained = constrainPosition(x, y);
      localStorage.setItem(STORAGE_KEYS.POSITION, JSON.stringify(constrained));
  }
  
  // —— 加载位置 ——
  function loadPosition() {
      const saved = localStorage.getItem(STORAGE_KEYS.POSITION);
      let position = {x: 20, y: 20}; // 默认位置
      
      if (saved) {
          try {
              position = JSON.parse(saved);
          } catch (e) {
              position = {x: 20, y: 20};
          }
      }
      
      // 加载时也进行边界检查,防止窗口大小改变后面板跑到屏幕外
      return constrainPosition(position.x, position.y);
  }

  // —— 辅助:检测压缩格式 ——
  function detectCompression(buf) {
    const b = new Uint8Array(buf);
    if (b.length >= 2) {
      if (b[0] === 0x1f && b[1] === 0x8b) return 'gzip';
      if (b[0] === 0x78 && (((b[0] << 8) | b[1]) % 31) === 0) return 'zlib';
    }
    return 'deflate';
  }

  // —— 判断是否为强化请求 ——
  function isEnhanceRequest(data) {
    if (typeof data === 'string') {
      try {
        // 检查是否包含 enhance:require 事件
        return data.includes('"enhance:require"') || data.includes('enhance:require');
      } catch (e) {
        return false;
      }
    }
    return false;
  }
  
  // —— 解析强化数据 ——
  function parseEnhanceData(data) {
    try {
      if (typeof data === 'string') {
        // 尝试解析Socket.IO格式的数据
        const match = data.match(/\["enhance:require",(.+)\]/);
        if (match) {
          const payload = JSON.parse(match[1]);
          if (payload.data && payload.data.resourceId) {
            return {
              resourceId: payload.data.resourceId,
              protectedResourceId: payload.data.protectedResourceId || null,
              user: payload.user ? payload.user.name : 'Unknown',
              fullPayload: payload // 保存完整的payload用于重构请求
            };
          }
        }
      }
    } catch (e) {
      // 解析失败,忽略
    }
    return null;
  }
  
  // —— 解析强化结果 ——
  function parseEnhanceResult(text) {
    try {
      const data = JSON.parse(text);
      if (data.data && data.data.hasOwnProperty('success') && data.data.enhanceResultId) {
        return {
          success: data.data.success,
          message: data.data.msg,
          resultId: data.data.enhanceResultId,
          user: data.user ? data.user.name : 'Unknown'
        };
      }
    } catch (e) {
      // 不是强化结果,忽略
    }
    return null;
  }
  
  // —— 解析物品等级 ——
  function parseItemLevel(itemId) {
    const match = itemId.match(/(.+?)\+(\d+)$/);
    if (match) {
      return {
        baseItem: match[1],
        level: parseInt(match[2], 10)
      };
    }
    return {
      baseItem: itemId,
      level: 0
    };
  }
  
  // —— 初始化统计数据 ——
  function initStats(itemId, targetLevel) {
    const parsed = parseItemLevel(itemId);
    enhanceStats = {
      baseItem: parsed.baseItem,
      currentLevel: parsed.level,
      targetLevel: targetLevel,
      maxReachedLevel: parsed.level, // 初始化为当前等级
      levelStats: {},
      totalAttempts: 0,
      totalSuccess: 0,
      startTime: Date.now()
    };
    
    // 初始化每级统计 - 始终从+1到目标等级
    for (let i = 0; i < targetLevel; i++) {
      enhanceStats.levelStats[i] = { attempts: 0, success: 0 };
    }
  }
  
  // —— 更新统计数据 ——
  function updateStats(result) {
    // 解析结果物品等级
    const resultItem = parseItemLevel(result.resultId);
    
    // 记录这次尝试
    const attemptLevel = enhanceStats.currentLevel;
    const levelStats = enhanceStats.levelStats[attemptLevel];
    if (levelStats) {
      levelStats.attempts++;
      enhanceStats.totalAttempts++;
      
      if (result.success) {
        levelStats.success++;
        enhanceStats.totalSuccess++;
      }
    }
    
    // 更新当前等级为结果等级
    enhanceStats.currentLevel = resultItem.level;
    
    // 更新历史最大等级
    if (resultItem.level > enhanceStats.maxReachedLevel) {
      enhanceStats.maxReachedLevel = resultItem.level;
    }
    
    updateStatsDisplay();
  }

  // —— 自动强化函数 ——
  function startAutoEnhance(ws) {
    if (enhanceTimer) {
      clearTimeout(enhanceTimer);
    }
    
    // 发送第一次强化请求
    sendEnhanceRequest(ws);
  }
  
  // —— 发送强化请求 ——
  function sendEnhanceRequest(ws) {
    if (!isAutoEnhancing || !ws || ws.readyState !== WebSocket.OPEN || !currentEnhanceItem || !storedEnhanceData) {
      return;
    }
    
    // 检查是否达到目标等级
    if (enhanceStats.currentLevel >= enhanceStats.targetLevel) {
      // 获取当前输入框的批量次数
      const currentInputValue = parseInt(batchCountInput.value, 10);
      
      // 批量次数-1,直接修改输入框的值
      if (currentInputValue > 1) {
        batchCountInput.value = currentInputValue - 1;
        BATCH_COUNT = currentInputValue - 1; // 同步内部变量
        currentBatchCount = currentInputValue - 1; // 同步当前批量次数
        saveConfig(); // 保存配置
        
        // 获取基础物品ID(去掉+数字后缀)
        const currentItemInfo = parseItemLevel(currentEnhanceItem.resourceId);
        const baseItemId = currentItemInfo.baseItem; // 基础物品ID,不包含+数字
        
        // 更新当前强化物品为基础版本
        currentEnhanceItem.resourceId = baseItemId;
        saveCurrentItem(); // 保存更新后的物品信息
        
        // 重置统计数据,准备下一轮强化(使用基础物品ID)
        initStats(baseItemId, TARGET_LEVEL);
        updateStatsDisplay();
        updateItemDisplay(currentEnhanceItem, `批量剩余: ${currentInputValue - 1}`);
        updateMinimizedDisplay();
        
        // Debug模式记录批量循环信息
        if (DEBUG_MODE) {
          console.group('🔄 [强化助手] 批量强化循环');
          console.log('批量信息:', {
            完成轮次: BATCH_COUNT - (currentInputValue - 1) + 1,
            剩余次数: currentInputValue - 1,
            基础物品ID: baseItemId,
            原强化物品ID: enhanceStats.baseItem + '+' + enhanceStats.targetLevel,
            时间: new Date().toLocaleTimeString()
          });
          console.groupEnd();
        }
        
        // 继续发送强化请求
        setTimeout(() => {
          sendEnhanceRequest(ws);
        }, ENHANCE_INTERVAL);
        return;
      }
      
      // 批量完成,停止自动强化并更新UI状态
      isAutoEnhancing = false;
      stopAutoEnhance();
      updateItemDisplay(currentEnhanceItem, '批量完成');
      updateToggleButtonState();
      updateMinimizedDisplay();
      return;
    }
    
    // 构造当前物品的强化请求,使用完整保存的数据
    const requestData = {
      user: storedEnhanceData.user,
      data: {
        resourceId: currentEnhanceItem.resourceId
      }
    };
    
    // 根据当前等级和设置决定是否使用保护材料
    if (storedEnhanceData.data && storedEnhanceData.data.protectedResourceId && 
        enhanceStats.currentLevel >= PROTECT_START_LEVEL) {
      requestData.data.protectedResourceId = storedEnhanceData.data.protectedResourceId;
    }
    
    const enhanceRequest = `42["enhance:require",${JSON.stringify(requestData)}]`;
    
    // Debug模式记录自动强化请求
    if (DEBUG_MODE) {
      console.group('🤖 [强化助手] 发送自动强化请求');
      console.log('请求数据:', enhanceRequest);
      console.log('构造的请求对象:', requestData);
      console.log('目标物品:', {
        物品ID: currentEnhanceItem.resourceId,
        保护材料ID: requestData.data.protectedResourceId || '无',
        当前等级: enhanceStats.currentLevel,
        目标等级: enhanceStats.targetLevel,
        批量进度: `${BATCH_COUNT - currentBatchCount + 1}/${BATCH_COUNT}`,
        剩余次数: currentBatchCount,
        保护设置: `≥${PROTECT_START_LEVEL}级使用`,
        实际使用保护: requestData.data.protectedResourceId ? '是' : '否',
        用户: requestData.user.name,
        时间: new Date().toLocaleTimeString()
      });
      console.groupEnd();
    }
    
    waitingForResult = true;
    ws.__originalSend(enhanceRequest);
  }
  
  // —— 处理强化结果 ——
  function handleEnhanceResult(result) {
    waitingForResult = false;
    
    // 总是更新当前强化物品为结果物品(不管成功失败)
    const wasFirstCapture = !currentEnhanceItem;
    
    currentEnhanceItem = {
      resourceId: result.resultId,
      user: result.user
    };
    
    // 保存到本地存储
    saveCurrentItem();
    
    // 如果是第一次捕获物品,启用按钮
    if (wasFirstCapture) {
      updateItemDisplay(currentEnhanceItem);
    } else {
      // 更新UI显示当前物品
      updateItemDisplay(currentEnhanceItem);
      
      // 更新统计数据(只有在自动强化时才统计)
      if (isAutoEnhancing) {
        updateStats(result);
      }
    }
    
    // 如果还在自动强化模式,延迟后继续
    if (isAutoEnhancing) {
      enhanceTimer = setTimeout(() => {
        sendEnhanceRequest(window.currentWS);
      }, ENHANCE_INTERVAL);
    }
  }

  function stopAutoEnhance() {
    if (enhanceTimer) {
      clearTimeout(enhanceTimer);
      enhanceTimer = null;
    }
    waitingForResult = false;
  }

  // —— 初始化配置 ——
  loadConfig();
  
  // Debug模式启动提示
  if (DEBUG_MODE) {
      console.log('🐛 [强化助手] 调试模式已启用,将记录所有WebSocket强化请求和结果');
  }
  
  // 如果有恢复的物品,延迟更新UI显示
  if (currentEnhanceItem) {
      setTimeout(() => {
          updateItemDisplay(currentEnhanceItem);
      }, 100);
  }
  
  // 初始化保护显示
  setTimeout(() => {
      updateProtectDisplay();
      // 初始化保护等级提示
      if (PROTECT_START_LEVEL === 0) {
          protectLevelHint.textContent = '不使用保护';
          protectLevelHint.style.color = '#f44336';
      } else {
          protectLevelHint.textContent = `≥${PROTECT_START_LEVEL}级使用保护`;
          protectLevelHint.style.color = '#aaa';
      }
      
      // 如果有恢复的物品,更新显示
      if (currentEnhanceItem) {
          updateItemDisplay(currentEnhanceItem);
      }
      
      // 如果页面加载时是收起状态,调整面板宽度和显示状态
      if (isMinimized) {
          panel.style.width = '280px';
          titleBar.style.display = 'none';
          mainContent.style.display = 'none';
          minimizedBar.style.display = 'flex';
      }
      
      // 初始化收起状态显示
      updateMinimizedDisplay();
  }, 100);
  
  // —— 创建浮动控制面板 ——
  const panel = document.createElement('div');
  panel.id = 'enhanceHelperPanel'; // 添加唯一ID
  const savedPos = loadPosition();
  panel.style.cssText = `
    position: fixed; top: ${savedPos.y}px; right: ${savedPos.x}px;
    width: 480px; padding: 12px;
    background: rgba(25,35,45,0.95); color: #fff;
    font-family: 'Consolas', 'Monaco', monospace; font-size: 12px;
    border-radius: 10px; z-index: 9999;
    cursor: move; border: 1px solid rgba(100,200,255,0.3);
    box-shadow: 0 6px 25px rgba(0,0,0,0.4);
    backdrop-filter: blur(5px);
  `;
  panel.innerHTML = `
    <div id="enhanceHelper_titleBar" style="cursor: default; margin-bottom:10px; font-weight:bold; color:#64B5F6; display:${isMinimized ? 'none' : 'flex'}; align-items:center;">
      <span>🛠️ 强化助手</span>
      <div style="margin-left:auto; display:flex; align-items:center; gap:6px;">
        <button id="enhanceHelper_minimizeBtn" style="
          padding:2px 6px; background:rgba(100,200,255,0.2); border:none; border-radius:3px;
          color:#64B5F6; cursor:pointer; font-size:10px;
        ">${isMinimized ? '📋' : '📌'}</button>
        <div style="font-size:10px; color:#888;">v2.5</div>
      </div>
    </div>
    
    <!-- 收起状态的小横条 -->
    <div id="enhanceHelper_minimizedBar" style="display:${isMinimized ? 'flex' : 'none'}; 
      background:rgba(0,0,0,0.5); padding:6px 8px; border-radius:6px; margin-bottom:8px;
      font-size:11px; color:#FFA726; align-items:center; justify-content:space-between;">
      <div id="enhanceHelper_minimizedStatus">等待强化结果...</div>
      <button id="enhanceHelper_expandBtn" style="
        padding:2px 6px; background:rgba(100,200,255,0.2); border:none; border-radius:3px;
        color:#64B5F6; cursor:pointer; font-size:10px; margin-left:8px;
      ">📋</button>
    </div>
    
    <div id="enhanceHelper_mainContent" style="display:${isMinimized ? 'none' : 'block'};">
      <!-- 主要内容区域:左右分布 -->
      <div style="display: flex; gap: 12px;">
        <!-- 左侧控制区 -->
        <div style="flex: 1; min-width: 220px;">
          <div style="background:rgba(0,0,0,0.3); padding:8px; border-radius:6px; margin-bottom:8px;">
            <div style="font-size:10px; color:#aaa; margin-bottom:4px;">目标物品:</div>
            <div id="enhanceHelper_itemDisplay" style="color:#FFA726; font-weight:bold; min-height:16px;">
              等待强化结果...
            </div>
            <div id="enhanceHelper_protectMaterialDisplay" style="font-size:9px; color:#81C784; margin-top:4px; min-height:12px;">
              <!-- 保护材料信息 -->
            </div>
          </div>
          
          <div style="display:flex; gap:8px; margin-bottom:8px;">
            <label style="flex:1;">
              目标等级:
              <input id="enhanceHelper_targetInput" type="number" min="1" max="15" value="${TARGET_LEVEL}"
                     style="width:100%; padding:4px; border-radius:4px; border:none; background:rgba(255,255,255,0.1); color:#fff; margin-top:2px;">
            </label>
            <label style="flex:1;">
              间隔(ms):
              <input id="enhanceHelper_intervalInput" type="number" min="100" value="${ENHANCE_INTERVAL}"
                     style="width:100%; padding:4px; border-radius:4px; border:none; background:rgba(255,255,255,0.1); color:#fff; margin-top:2px;">
            </label>
          </div>
          
          <div style="display:flex; gap:8px; margin-bottom:8px;">
            <label style="flex:1;">
              批量次数:
              <input id="enhanceHelper_batchCountInput" type="number" min="1" max="99" value="${BATCH_COUNT}"
                     style="width:100%; padding:4px; border-radius:4px; border:none; background:rgba(255,255,255,0.1); color:#fff; margin-top:2px;"
                     title="连续强化多少个物品到目标等级">
            </label>
            <div style="flex:1; font-size:10px; color:#aaa; padding:4px;">
              <div style="font-size:9px; color:#666;">剩余次数会自动减少</div>
              <div style="font-size:9px; color:#666;">1=单次强化</div>
            </div>
          </div>
          
          <div style="display:flex; gap:8px; margin-bottom:8px;">
            <label style="flex:1;">
              保护等级:
              <input id="enhanceHelper_protectStartLevelInput" type="number" min="0" max="15" value="${PROTECT_START_LEVEL}"
                     style="width:100%; padding:4px; border-radius:4px; border:none; background:rgba(255,255,255,0.1); color:#fff; margin-top:2px;"
                     title="从几级开始使用保护材料 (0=不使用)">
            </label>
            <div style="flex:1; font-size:10px; color:#aaa; padding:4px;">
              <div id="enhanceHelper_protectLevelHint">≥${PROTECT_START_LEVEL}级使用保护</div>
              <div style="font-size:9px; color:#666;">0=不使用保护</div>
            </div>
          </div>
          
          <div style="margin-bottom:8px;">
            <label style="display:flex; align-items:center; font-size:11px; color:#aaa; cursor:pointer;">
              <input id="enhanceHelper_debugModeCheckbox" type="checkbox" ${DEBUG_MODE ? 'checked' : ''}
                     style="margin-right:6px; transform:scale(0.9);">
              <span>🐛 调试模式 (记录WS强化请求)</span>
            </label>
          </div>
          
          <button id="enhanceHelper_toggleBtn" style="
            width:100%; padding:10px;
            background:linear-gradient(45deg, #4CAF50, #45a049); color:white; border:none;
            border-radius:6px; cursor:pointer; font-size:13px; font-weight:bold;
            transition: all 0.3s ease;
          " disabled>🚀 开始强化</button>
          
          <div style="display:flex; justify-content:space-between; font-size:10px; color:#aaa; margin-top:8px;">
            <span>状态: <span id="enhanceHelper_status" style="color:#FFA726;">待机中</span></span>
            <span id="enhanceHelper_counter">就绪</span>
          </div>
          
          <button id="enhanceHelper_clearDataBtn" style="
            width:100%; padding:6px; margin-top:6px;
            background:rgba(244,67,54,0.8); color:white; border:none;
            border-radius:4px; cursor:pointer; font-size:10px;
            transition: all 0.3s ease;
          ">🗑️ 清除保存数据</button>
        </div>
        
        <!-- 右侧统计区 -->
        <div style="flex: 1; min-width: 220px;">
          <div style="background:rgba(0,0,0,0.3); padding:8px; border-radius:6px; height: 100%;">
            <div style="font-size:10px; color:#aaa; margin-bottom:6px; display:flex; align-items:center;">
              <span>📊 强化统计</span>
            </div>
            <div id="enhanceHelper_statsDisplay" style="font-size:10px; color:#FFA726;">
              等待开始强化...
            </div>
          </div>
        </div>
      </div>
    </div>
  `;
  document.body.appendChild(panel);

  // —— 获取控制元素 ——
  const targetInput = document.getElementById('enhanceHelper_targetInput');
  const intervalInput = document.getElementById('enhanceHelper_intervalInput');
  const batchCountInput = document.getElementById('enhanceHelper_batchCountInput');
  const protectStartLevelInput = document.getElementById('enhanceHelper_protectStartLevelInput');
  const debugCheckbox = document.getElementById('enhanceHelper_debugModeCheckbox');
  const toggleBtn = document.getElementById('enhanceHelper_toggleBtn');
  const statusSpan = document.getElementById('enhanceHelper_status');
  const itemDisplay = document.getElementById('enhanceHelper_itemDisplay');
  const protectMaterialDisplay = document.getElementById('enhanceHelper_protectMaterialDisplay');
  const protectLevelHint = document.getElementById('enhanceHelper_protectLevelHint');
  const counterSpan = document.getElementById('enhanceHelper_counter');
  const statsDisplay = document.getElementById('enhanceHelper_statsDisplay');
  const clearDataBtn = document.getElementById('enhanceHelper_clearDataBtn');
  
  // 收起/展开相关元素
  const titleBar = document.getElementById('enhanceHelper_titleBar');
  const minimizeBtn = document.getElementById('enhanceHelper_minimizeBtn');
  const expandBtn = document.getElementById('enhanceHelper_expandBtn');
  const mainContent = document.getElementById('enhanceHelper_mainContent');
  const minimizedBar = document.getElementById('enhanceHelper_minimizedBar');
  const minimizedStatus = document.getElementById('enhanceHelper_minimizedStatus');

  // —— 拖拽逻辑 ——
  (function makeDraggable(el) {
    let isDown = false, offsetX = 0, offsetY = 0, hasMoved = false;
    el.addEventListener('mousedown', e => {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON') return;
      isDown = true;
      hasMoved = false;
      offsetX = e.clientX - el.offsetLeft;
      offsetY = e.clientY - el.offsetTop;
    });
    document.addEventListener('mousemove', e => {
      if (!isDown) return;
      hasMoved = true;
      const newX = e.clientX - offsetX;
      const newY = e.clientY - offsetY;
      el.style.left = newX + 'px';
      el.style.top = newY + 'px';
      el.style.right = 'auto'; // 拖拽时清除right定位
    });
    document.addEventListener('mouseup', () => { 
      if (isDown && hasMoved) {
        // 只有真正拖拽过才应用边界检查
        setTimeout(() => {
          const rect = el.getBoundingClientRect();
          const rightDistance = window.innerWidth - rect.right;
          const topDistance = rect.top;
          
          // 保存并应用边界约束后的位置
          const constrained = constrainPosition(rightDistance, topDistance);
          savePosition(constrained.x, constrained.y);
          
          // 重新设置为right定位
          el.style.right = constrained.x + 'px';
          el.style.top = constrained.y + 'px';
          el.style.left = 'auto';
        }, 0); // 使用setTimeout避免干扰点击事件
      }
      isDown = false;
      hasMoved = false;
    });
  })(panel);

  // —— 更新保护材料显示 ——
  function updateProtectDisplay() {
    if (storedEnhanceData && storedEnhanceData.data && storedEnhanceData.data.protectedResourceId) {
      const protectMaterial = storedEnhanceData.data.protectedResourceId;
      if (PROTECT_START_LEVEL === 0) {
        protectMaterialDisplay.innerHTML = `🛡️ 保护: ${protectMaterial} <span style="color:#f44336;">(已禁用)</span>`;
      } else {
        protectMaterialDisplay.innerHTML = `🛡️ 保护: ${protectMaterial} <span style="color:#64B5F6;">(≥${PROTECT_START_LEVEL}级)</span>`;
      }
    } else {
      protectMaterialDisplay.textContent = '无保护材料';
    }
  }
  
  // —— 更新UI显示 ——
  function updateItemDisplay(itemInfo, customStatus = null) {
    if (itemInfo) {
      itemDisplay.textContent = itemInfo.resourceId; // 保持英文原始名称
      itemDisplay.title = `用户: ${itemInfo.user}`;
      toggleBtn.disabled = false;
      toggleBtn.style.opacity = '1';
      statusSpan.textContent = customStatus || '就绪';
      statusSpan.style.color = customStatus === '已完成' ? '#4CAF50' : '#4CAF50';
      counterSpan.textContent = customStatus === '已完成' ? '完成' : '已捕获';
    } else {
      itemDisplay.textContent = '等待强化结果...';
      itemDisplay.title = '';
      toggleBtn.disabled = true;
      toggleBtn.style.opacity = '0.5';
      statusSpan.textContent = '等待中';
      statusSpan.style.color = '#FFA726';
      counterSpan.textContent = '就绪';
    }
    
    // 更新保护材料显示
    updateProtectDisplay();
    // 更新收起状态显示
    updateMinimizedDisplay();
  }
  
  // —— 更新统计显示 ——
  function updateStatsDisplay() {
    if (!enhanceStats.baseItem) {
      statsDisplay.innerHTML = '等待开始强化...';
      return;
    }
    
    const totalRate = enhanceStats.totalAttempts > 0 ? 
      (enhanceStats.totalSuccess / enhanceStats.totalAttempts * 100).toFixed(1) : '0.0';
    
    let html = `
      <div style="margin-bottom:6px; padding-bottom:6px; border-bottom:1px solid rgba(255,255,255,0.1);">
        <div style="color:#64B5F6; font-weight:bold; margin-bottom:2px;">${enhanceStats.baseItem}</div>
        <div style="font-size:11px; color:#FFA726;">
          进度: Lv${enhanceStats.currentLevel}/${enhanceStats.targetLevel} | 
          总计: ${enhanceStats.totalAttempts}次 (${totalRate}%)
        </div>
      </div>
    `;
    
    // 显示每级详细统计 - 每级一行,从高到低排序
    const levels = Object.keys(enhanceStats.levelStats).sort((a, b) => parseInt(b) - parseInt(a));
    if (levels.length > 0) {
      html += '<div>';
      levels.forEach(level => {
        const stats = enhanceStats.levelStats[level];
        const levelNum = parseInt(level);
        const targetLevelNum = levelNum + 1;
        const rate = stats.attempts > 0 ? (stats.success / stats.attempts * 100).toFixed(1) : '0.0';
        const targetLevel = levelNum + 1; // 目标等级 (Lv1, Lv2, etc.)
        const currentItemLevel = enhanceStats.currentLevel; // 当前物品等级
        const maxReachedLevel = enhanceStats.maxReachedLevel; // 历史最大等级
        
        // 确定显示样式
        let bgColor, textColor;
        if (targetLevel === currentItemLevel + 1) {
          // 当前正在强化的目标等级(蓝色)- 优先级最高
          bgColor = 'rgba(100,181,246,0.2)';
          textColor = '#64B5F6';
        } else if (targetLevel <= maxReachedLevel) {
          // 历史上到过的等级(绿色)
          bgColor = 'rgba(76,175,80,0.1)';
          textColor = '#81C784';
        } else {
          // 还没到过的等级(灰色)
          bgColor = 'transparent';
          textColor = '#666';
        }
        
        const displayText = `${stats.attempts}次 (${rate}%)`;
        
        html += `
          <div style="
            display:flex; justify-content:space-between; align-items:center;
            padding:2px 4px; margin:1px 0; border-radius:3px;
            background:${bgColor}; font-size:9px; color:${textColor};
          ">
            <span>Lv${targetLevelNum}</span>
            <span>${displayText}</span>
          </div>
        `;
      });
      html += '</div>';
    }
    
    statsDisplay.innerHTML = html;
  }
  
  // —— 收起/展开功能 ——
  function toggleMinimize() {
    isMinimized = !isMinimized;
    
    if (isMinimized) {
      titleBar.style.display = 'none';
      mainContent.style.display = 'none';
      minimizedBar.style.display = 'flex';
      panel.style.width = '280px';
    } else {
      titleBar.style.display = 'flex';
      mainContent.style.display = 'block';
      minimizedBar.style.display = 'none';
      minimizeBtn.textContent = '📌';
      panel.style.width = '480px';
    }
    
    saveConfig();
    updateMinimizedDisplay();
  }
  
  // —— 更新收起状态显示 ——
  function updateMinimizedDisplay() {
    if (!isMinimized) return;
    
    let statusText = '等待强化结果...';
    
    if (currentEnhanceItem) {
      const itemInfo = parseItemLevel(currentEnhanceItem.resourceId);
      const baseItem = itemInfo.baseItem.length > 15 ? itemInfo.baseItem.substring(0, 15) + '..' : itemInfo.baseItem;
      const currentLevel = itemInfo.level;
      
      if (isAutoEnhancing) {
        // 获取当前输入框的剩余次数
        const remainingCount = parseInt(batchCountInput.value, 10);
        const batchInfo = remainingCount > 1 ? ` [剩余${remainingCount}次]` : '';
        statusText = `🔨 ${baseItem} +${currentLevel} → +${TARGET_LEVEL}${batchInfo}`;
      } else {
        const status = enhanceStats.currentLevel >= enhanceStats.targetLevel ? '已完成' : '就绪';
        statusText = `${status}: ${baseItem} +${currentLevel}`;
        if (status === '已完成') {
          statusText = `✅ ${baseItem} +${currentLevel} 已完成`;
        }
      }
    }
    
    minimizedStatus.textContent = statusText;
  }
  
  // —— 更新按钮状态 ——
  function updateToggleButtonState() {
    if (isAutoEnhancing) {
      toggleBtn.innerHTML = '⏹️ 停止强化';
      toggleBtn.style.background = 'linear-gradient(45deg, #f44336, #d32f2f)';
      statusSpan.textContent = '运行中';
      statusSpan.style.color = '#4CAF50';
      counterSpan.textContent = '活动中';
    } else {
      toggleBtn.innerHTML = '🚀 开始强化';
      toggleBtn.style.background = 'linear-gradient(45deg, #4CAF50, #45a049)';
      
      if (enhanceStats.currentLevel >= enhanceStats.targetLevel && enhanceStats.baseItem) {
        statusSpan.textContent = '已完成';
        statusSpan.style.color = '#4CAF50';
        counterSpan.textContent = '完成';
      } else {
        statusSpan.textContent = '已停止';
        statusSpan.style.color = '#f44336';
        counterSpan.textContent = '就绪';
      }
    }
  }
  
  // —— 双击标题栏重置位置 ——
  titleBar.addEventListener('dblclick', () => {
    const defaultPos = {x: 20, y: 20};
    panel.style.right = defaultPos.x + 'px';
    panel.style.top = defaultPos.y + 'px';
    panel.style.left = 'auto';
    savePosition(defaultPos.x, defaultPos.y);
    
    // 显示重置提示
    const oldTitle = titleBar.querySelector('span').textContent;
    titleBar.querySelector('span').textContent = '🔄 位置已重置';
    setTimeout(() => {
      titleBar.querySelector('span').textContent = oldTitle;
    }, 1000);
  });

  // —— 事件监听器 ——
  targetInput.addEventListener('change', e => {
    const v = parseInt(e.target.value, 10);
    if (!isNaN(v) && v > 0 && v <= 15) {
      TARGET_LEVEL = v;
      saveConfig();
    }
  });

  intervalInput.addEventListener('change', e => {
    const v = parseInt(e.target.value, 10);
    if (!isNaN(v) && v >= 100) {
      ENHANCE_INTERVAL = v;
      saveConfig();
    }
  });
  
  batchCountInput.addEventListener('change', e => {
    const v = parseInt(e.target.value, 10);
    if (!isNaN(v) && v >= 1 && v <= 99) {
      BATCH_COUNT = v;
      saveConfig();
    }
  });
  
        protectStartLevelInput.addEventListener('change', e => {
      const v = parseInt(e.target.value, 10);
      if (!isNaN(v) && v >= 0 && v <= 15) {
        PROTECT_START_LEVEL = v;
        saveConfig();
        updateProtectDisplay(); // 更新保护显示
        // 更新提示文本
        if (v === 0) {
          protectLevelHint.textContent = '不使用保护';
          protectLevelHint.style.color = '#f44336';
        } else {
          protectLevelHint.textContent = `≥${v}级使用保护`;
          protectLevelHint.style.color = '#aaa';
        }
      }
    });
  
  debugCheckbox.addEventListener('change', e => {
    DEBUG_MODE = e.target.checked;
    saveConfig();
    console.log(`[强化助手] 调试模式已${DEBUG_MODE ? '开启' : '关闭'}`);
  });

  toggleBtn.addEventListener('click', () => {
    if (!isAutoEnhancing) {
      if (!currentEnhanceItem) {
        return; // 按钮应该是禁用状态
      }
      
      // 获取当前批量次数设置
      const inputBatchCount = parseInt(batchCountInput.value, 10);
      BATCH_COUNT = inputBatchCount;
      currentBatchCount = inputBatchCount;
      
      // 如果是批量强化(>1次),确保从基础物品开始
      if (inputBatchCount > 1) {
        const currentItemInfo = parseItemLevel(currentEnhanceItem.resourceId);
        const baseItemId = currentItemInfo.baseItem; // 基础物品ID,不包含+数字
        
        // 更新当前强化物品为基础版本
        currentEnhanceItem.resourceId = baseItemId;
        saveCurrentItem(); // 保存更新后的物品信息
        
        // 初始化统计数据(使用基础物品ID)
        initStats(baseItemId, TARGET_LEVEL);
        
        // Debug模式记录批量开始信息
        if (DEBUG_MODE) {
          console.group('🚀 [强化助手] 开始批量强化');
          console.log('批量设置:', {
            批量次数: inputBatchCount,
            基础物品ID: baseItemId,
            原物品ID: currentItemInfo.baseItem + (currentItemInfo.level > 0 ? '+' + currentItemInfo.level : ''),
            目标等级: TARGET_LEVEL,
            时间: new Date().toLocaleTimeString()
          });
          console.groupEnd();
        }
      } else {
        // 单次强化,使用当前物品
        initStats(currentEnhanceItem.resourceId, TARGET_LEVEL);
      }
      
      updateStatsDisplay();
      
      // 开始自动强化
      isAutoEnhancing = true;
      updateToggleButtonState();
      updateMinimizedDisplay();
      
      if (window.currentWS) {
        startAutoEnhance(window.currentWS);
      }
    } else {
      // 停止自动强化
      isAutoEnhancing = false;
      stopAutoEnhance();
      updateToggleButtonState();
      updateMinimizedDisplay();
    }
  });
  
  // —— 收起/展开按钮事件 ——
  minimizeBtn.addEventListener('click', toggleMinimize);
  expandBtn.addEventListener('click', toggleMinimize);
  
  // —— 清除数据按钮事件 ——
  clearDataBtn.addEventListener('click', () => {
    if (confirm('确定要清除所有保存的数据吗?这将清除当前强化物品和请求数据。')) {
      // 清除内存中的数据
      currentEnhanceItem = null;
      storedEnhanceData = null;
      currentBatchCount = 0; // 重置批量次数
      
      // 重置批量次数输入框
      batchCountInput.value = 1;
      BATCH_COUNT = 1;
      
      // 清除本地存储
      localStorage.removeItem(STORAGE_KEYS.CURRENT_ITEM);
      localStorage.removeItem(STORAGE_KEYS.STORED_REQUEST);
      
      // 重置UI
      updateItemDisplay(null);
      updateProtectDisplay();
      
      // 如果正在强化,停止强化
      if (isAutoEnhancing) {
        isAutoEnhancing = false;
        stopAutoEnhance();
        updateToggleButtonState();
      }
      
      // 更新收起状态显示
      updateMinimizedDisplay();
      
      // 保存配置
      saveConfig();
    }
  });

  // —— 拦截全局 WebSocket(增强助手命名空间) ——
  const NativeWS = window.WebSocket;
  
  // 检查是否已经被其他脚本拦截
  if (!window.WebSocket.__enhanceHelperIntercepted) {
    const OriginalWebSocket = window.WebSocket;
    
    window.WebSocket = function(url, protocols) {
      const ws = protocols ? new OriginalWebSocket(url, protocols) : new OriginalWebSocket(url);
      
      // 保存当前WebSocket实例
      window.currentWS = ws;

    // —— 拦截 send ——
    const originalSend = ws.send;
    ws.__originalSend = originalSend; // 保存原始方法供自动强化使用
    ws.send = function(data) {
      // 检查是否为强化请求
      if (isEnhanceRequest(data)) {
        const enhanceData = parseEnhanceData(data);
        if (enhanceData && enhanceData.fullPayload) {
          // 储存完整的强化数据供后续自动使用
          storedEnhanceData = enhanceData.fullPayload;
          saveStoredRequest(); // 保存到本地存储
          updateProtectDisplay(); // 更新保护材料显示
          
          // 检测到手动强化指令,如果批量次数为0,设为1
          if (currentBatchCount === 0) {
            currentBatchCount = 1;
            batchCountInput.value = 1;
            BATCH_COUNT = 1;
            saveConfig(); // 保存批量次数
            updateMinimizedDisplay(); // 更新收起状态显示
          }
          
          // Debug模式记录强化请求保存
          if (DEBUG_MODE) {
            console.group('💾 [强化助手] 保存强化请求数据');
            console.log('原始数据:', data);
            console.log('保存的完整数据:', storedEnhanceData);
            console.log('解析结果:', {
              物品ID: enhanceData.resourceId,
              保护材料ID: enhanceData.protectedResourceId || '无',
              用户: enhanceData.user,
              批量次数设置: currentBatchCount,
              时间: new Date().toLocaleTimeString()
            });
            console.groupEnd();
          }
        }
        
        // Debug模式记录强化请求拦截
        if (DEBUG_MODE) {
          console.group('🔨 [强化助手] 拦截到强化请求');
          console.log('原始数据:', data);
          if (enhanceData) {
            console.log('解析结果:', {
              物品ID: enhanceData.resourceId,
              保护材料ID: enhanceData.protectedResourceId || '无',
              用户: enhanceData.user,
              时间: new Date().toLocaleTimeString()
            });
          }
          console.groupEnd();
        }
      }
      
      // 正常发送原始请求,不影响游戏运行
      originalSend.call(this, data);
    };

    // —— 拦截接收消息并解压 ——
    ws.addEventListener('message', ev => {
      if (ev.data instanceof ArrayBuffer) {
        try {
          const format = detectCompression(ev.data);
          let text;
          switch (format) {
            case 'gzip':
              text = pako.ungzip(new Uint8Array(ev.data), { to: 'string' });
              break;
            case 'zlib':
              text = pako.inflate(new Uint8Array(ev.data), { to: 'string' });
              break;
            default:
              text = pako.inflateRaw(new Uint8Array(ev.data), { to: 'string' });
          }
          
          // 检查是否为强化结果(不管是否在等待,都要处理)
          const enhanceResult = parseEnhanceResult(text);
          if (enhanceResult) {
            // Debug模式记录强化结果
            if (DEBUG_MODE) {
              console.group('✨ [强化助手] 拦截到强化结果');
              console.log('原始数据:', text);
              console.log('解析结果:', {
                成功: enhanceResult.success,
                消息: enhanceResult.message,
                结果物品ID: enhanceResult.resultId,
                用户: enhanceResult.user,
                时间: new Date().toLocaleTimeString()
              });
              // 如果有保存的请求数据,也显示相关信息
              if (storedEnhanceData && storedEnhanceData.data) {
                console.log('关联的请求信息:', {
                  原始物品ID: storedEnhanceData.data.resourceId,
                  保护材料ID: storedEnhanceData.data.protectedResourceId || '无'
                });
              }
              console.groupEnd();
            }
            
            handleEnhanceResult(enhanceResult);
          }
        } catch (err) {
          // 解压失败,忽略
        }
      }
    });
    
    // WebSocket关闭时清理
    ws.addEventListener('close', () => {
      if (isAutoEnhancing) {
        stopAutoEnhance();
        isAutoEnhancing = false;
        updateToggleButtonState();
        statusSpan.textContent = '连接断开';
        statusSpan.style.color = '#f44336';
        counterSpan.textContent = '离线';
        updateMinimizedDisplay();
      }
    });

    return ws;
  };

    // 继承原型与静态属性
    window.WebSocket.prototype = OriginalWebSocket.prototype;
    Object.getOwnPropertyNames(OriginalWebSocket).forEach(prop => {
      if (!(prop in window.WebSocket)) {
        window.WebSocket[prop] = OriginalWebSocket[prop];
      }
    });
    
    // 标记已被强化助手拦截
    window.WebSocket.__enhanceHelperIntercepted = true;
  }

  // —— 窗口大小改变时检查面板位置 ——
  window.addEventListener('resize', () => {
    const rect = panel.getBoundingClientRect();
    const rightDistance = window.innerWidth - rect.right;
    const topDistance = rect.top;
    
    // 检查并应用边界约束
    const constrained = constrainPosition(rightDistance, topDistance);
    
    // 如果位置需要调整,立即应用
    if (constrained.x !== rightDistance || constrained.y !== topDistance) {
      panel.style.right = constrained.x + 'px';
      panel.style.top = constrained.y + 'px';
      panel.style.left = 'auto';
      savePosition(constrained.x, constrained.y);
    }
  });

})(); 

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址