|
|
以管理员打开程序即可自动运行,初次修改为999999,低于500000将再次修改为999999。游戏金钱地址用CE修改器找到的,目前仅找到了修改金钱的方法,已经做到了自动修改。其他建造速度和超级武器未找到基址,欢迎各位大佬提供帮助。目前仅测试了红警2之心灵终结可用,其他版本未测试。
import pymem
import pymem.process
import psutil
import time
import sys
import threading
import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
import ctypes
class MoneyMonitorGUI:
def __init__(self, root):
self.root = root
self.root.title("红警2金钱监控器")
self.root.geometry("600x580")
self.root.resizable(True, True)
# 检查是否以管理员身份运行
if not self.is_admin():
self.show_admin_warning()
return
# 初始化监控器
self.monitor = MoneyMonitor()
self.monitor_thread = None
# 创建界面
self.create_widgets()
# 重定向输出到文本框
self.redirect_output()
# 自动启动监控
self.start_monitor()
def is_admin(self):
"""检查是否以管理员身份运行"""
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
def show_admin_warning(self):
"""显示管理员权限警告"""
# 创建一个临时的顶层窗口用于显示警告
temp_window = tk.Tk()
temp_window.withdraw() # 隐藏主窗口
messagebox.showerror("权限错误",
"此程序需要以管理员身份运行才能正常工作!\n\n"
"请右键点击程序图标,选择「以管理员身份运行」。")
temp_window.destroy()
self.root.destroy()
sys.exit(1)
def create_widgets(self):
# 主框架
main_frame = ttk.Frame(self.root, padding="10")
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# 配置网格权重
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)
main_frame.columnconfigure(1, weight=1)
main_frame.rowconfigure(4, weight=1)
# 标题
title_label = ttk.Label(main_frame, text="红警2金钱监控器", font=("Arial", 16, "bold"))
title_label.grid(row=0, column=0, columnspan=3, pady=(0, 20))
# 操作按钮框架
button_frame = ttk.LabelFrame(main_frame, text="操作选项", padding="10")
button_frame.grid(row=1, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=(0, 10))
ttk.Button(button_frame, text="单次修改金钱", command=self.single_modify).pack(side=tk.LEFT, padx=(0, 10))
self.start_button = ttk.Button(button_frame, text="停止监控", command=self.toggle_monitor)
self.start_button.pack(side=tk.LEFT, padx=(0, 10))
# 参数设置框架
settings_frame = ttk.LabelFrame(main_frame, text="监控参数设置", padding="10")
settings_frame.grid(row=2, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=(0, 10))
# 更新间隔
ttk.Label(settings_frame, text="更新间隔(秒):").grid(row=0, column=0, sticky=tk.W, padx=(0, 5))
self.interval_var = tk.StringVar(value=str(self.monitor.update_interval))
ttk.Entry(settings_frame, textvariable=self.interval_var, width=10).grid(row=0, column=1, sticky=tk.W, padx=(0, 10))
# 自动补充阈值和目标金钱值在同一行
ttk.Label(settings_frame, text="自动补充阈值:").grid(row=0, column=2, sticky=tk.W, padx=(10, 5))
self.threshold_var = tk.StringVar(value=str(self.monitor.min_money_threshold))
ttk.Entry(settings_frame, textvariable=self.threshold_var, width=10).grid(row=0, column=3, sticky=tk.W, padx=(0, 5))
ttk.Label(settings_frame, text="目标金钱值:").grid(row=0, column=4, sticky=tk.W, padx=(5, 5))
self.target_var = tk.StringVar(value=str(self.monitor.target_money))
ttk.Entry(settings_frame, textvariable=self.target_var, width=10).grid(row=0, column=5, sticky=tk.W, padx=(0, 10))
# 应用设置按钮
ttk.Button(settings_frame, text="应用设置", command=self.apply_settings).grid(row=1, column=0, columnspan=6, pady=(10, 0))
# 状态显示框架
status_frame = ttk.LabelFrame(main_frame, text="运行状态", padding="10")
status_frame.grid(row=3, column=0, columnspan=3, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
status_frame.columnconfigure(0, weight=1)
status_frame.rowconfigure(0, weight=1)
# 日志文本框
self.log_text = scrolledtext.ScrolledText(status_frame, height=15, state='disabled')
self.log_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# 清空日志按钮
ttk.Button(status_frame, text="清空日志", command=self.clear_log).grid(row=1, column=0, pady=(5, 0))
def redirect_output(self):
# 重定向print输出到文本框
import io
class TextRedirector(io.StringIO):
def __init__(self, widget):
super().__init__()
self.widget = widget
def write(self, s):
self.widget.config(state='normal')
self.widget.insert(tk.END, s)
self.widget.see(tk.END)
self.widget.config(state='disabled')
sys.stdout = TextRedirector(self.log_text)
def single_modify(self):
# 在新线程中执行单次修改,避免阻塞GUI
threading.Thread(target=self._single_modify_thread, daemon=True).start()
def _single_modify_thread(self):
print("开始单次修改金钱...")
self.monitor.single_modify()
def toggle_monitor(self):
if self.monitor.running:
self.stop_monitor()
else:
self.start_monitor()
def start_monitor(self):
# 应用当前设置
self.apply_settings()
# 在新线程中启动监控
self.monitor.running = True
self.monitor_thread = threading.Thread(target=self.monitor.monitor_loop, daemon=True)
self.monitor_thread.start()
self.start_button.config(text="停止监控")
print("监控已启动...")
def stop_monitor(self):
if self.monitor.running:
self.monitor.running = False
self.start_button.config(text="启动监控")
print("监控已停止...")
def apply_settings(self):
try:
interval = int(self.interval_var.get())
threshold = int(self.threshold_var.get())
target = int(self.target_var.get())
self.monitor.set_monitor_settings(interval, threshold, target)
print(f"参数已更新: 间隔={interval}s, 阈值={threshold}, 目标={target}")
except ValueError:
messagebox.showerror("错误", "请输入有效的数字参数")
def clear_log(self):
self.log_text.config(state='normal')
self.log_text.delete(1.0, tk.END)
self.log_text.config(state='disabled')
class MoneyMonitor:
def __init__(self):
self.running = False
self.pm = None
self.base_address = None
self.update_interval = 10 # 修改为10秒
self.min_money_threshold = 500000 # 修改阈值为500000
self.target_money = 999999 # 修改目标值为999999
def get_dynamic_base_address(self):
"""动态获取当前游戏的基址"""
try:
# 查找游戏进程
pid = None
for proc in psutil.process_iter(['pid', 'name']):
if proc.info['name'] and 'gamemd.exe' in proc.info['name'].lower():
pid = proc.info['pid']
break
if not pid:
return None, None
# 连接到进程并获取基址
pm = pymem.Pymem()
pm.open_process_from_id(pid)
game_module = pymem.process.module_from_name(pm.process_handle, "gamemd.exe")
return pm, game_module.lpBaseOfDll if game_module else None
except Exception as e:
print(f"获取基址失败: {e}")
return None, None
def calculate_money_addresses(self):
"""计算两个金钱地址"""
try:
if not self.pm or not self.base_address:
return None, None
# 渲染地址
render_address = self.base_address + 0x484D08
# 实际地址(通过指针链)
base_ptr = self.base_address + 0x00683D4C
level1 = self.pm.read_int(base_ptr)
actual_address = level1 + 0x30C
return render_address, actual_address
except Exception as e:
print(f"计算地址失败: {e}")
return None, None
def read_money_values(self, render_addr, actual_addr):
"""读取两个金钱地址的值"""
try:
render_value = self.pm.read_int(render_addr)
actual_value = self.pm.read_int(actual_addr)
return render_value, actual_value
except Exception as e:
print(f"读取金钱值失败: {e}")
return None, None
def write_money_values(self, render_addr, actual_addr, value):
"""写入两个金钱地址的值"""
try:
self.pm.write_int(render_addr, value)
self.pm.write_int(actual_addr, value)
return True
except Exception as e:
print(f"写入金钱值失败: {e}")
return False
def auto_refill_money(self, render_addr, actual_addr):
"""自动补充金钱"""
try:
render_value, actual_value = self.read_money_values(render_addr, actual_addr)
if render_value is None or actual_value is None:
return False
# 如果任意一个值低于阈值,就补充
if render_value < self.min_money_threshold or actual_value < self.min_money_threshold:
success = self.write_money_values(render_addr, actual_addr, self.target_money)
if success:
print(f"💰 自动补充: {max(render_value, actual_value)} -> {self.target_money}")
return success
return True
except Exception as e:
print(f"自动补充失败: {e}")
return False
def single_modify(self):
"""单次修改金钱"""
self.pm, self.base_address = self.get_dynamic_base_address()
if not self.pm or not self.base_address:
print("无法连接到游戏进程")
return False
print(f"检测到游戏基址: 0x{self.base_address:X}")
render_addr, actual_addr = self.calculate_money_addresses()
if not render_addr or not actual_addr:
print("计算地址失败")
return False
print(f"渲染地址: 0x{render_addr:X}")
print(f"实际地址: 0x{actual_addr:X}")
# 读取当前值
render_value, actual_value = self.read_money_values(render_addr, actual_addr)
if render_value is None or actual_value is None:
print("读取当前值失败")
return False
# 计算差值
diff = abs(render_value - actual_value)
print(f"当前渲染: {render_value}, 实际: {actual_value}, 差值: {diff}")
# 修改为目标值
success = self.write_money_values(render_addr, actual_addr, self.target_money)
if success:
print(f"✅ 修改成功! {actual_value} -> {self.target_money}")
return success
def monitor_loop(self):
"""监控循环"""
print(f"开始监控金钱... (更新间隔: {self.update_interval}秒)")
print(f"自动补充阈值: {self.min_money_threshold}")
print(f"目标金钱值: {self.target_money}")
print("点击 GUI 中的停止按钮停止监控")
last_base_address = None
while self.running:
try:
# 重新获取进程和基址(处理游戏重启)
self.pm, self.base_address = self.get_dynamic_base_address()
if not self.pm or not self.base_address:
print("❌ 游戏进程未找到,等待重新连接...")
time.sleep(5)
continue
# 检查基址是否变化(游戏重启)
if last_base_address != self.base_address:
print(f"🔄 检测到游戏基址: 0x{self.base_address:X}")
last_base_address = self.base_address
# 计算地址
render_addr, actual_addr = self.calculate_money_addresses()
if not render_addr or not actual_addr:
print("❌ 计算地址失败,跳过本次更新")
time.sleep(self.update_interval)
continue
# 读取当前值
render_value, actual_value = self.read_money_values(render_addr, actual_addr)
if render_value is None or actual_value is None:
print("❌ 读取值失败,跳过本次更新")
time.sleep(self.update_interval)
continue
print(f"当前金钱为:{actual_value},低于补充阈值将自动改为{self.target_money},请放心游戏...")
# 自动补充
self.auto_refill_money(render_addr, actual_addr)
time.sleep(self.update_interval)
except Exception as e:
print(f"监控循环错误: {e}")
time.sleep(self.update_interval)
def start_monitor(self):
"""开始监控"""
self.running = True
self.monitor_loop()
def set_monitor_settings(self, interval=10, threshold=500000, target=999999):
"""设置监控参数"""
self.update_interval = interval
self.min_money_threshold = threshold
self.target_money = target
def main():
root = tk.Tk()
app = MoneyMonitorGUI(root)
root.mainloop()
if __name__ == "__main__":
main()
复制代码 |
|