import pymem import pymem.process import tkinter as tk from tkinter import ttk, messagebox import threading import time # ===================== 罪恶都市 1.0原版 偏移 ===================== # 错误写法 # OFFSET_PLAYER_PTR = 0x0094AD28 # 正确写法 OFFSET_PLAYER_PTR = 0x0054AD28 # OFFSET_HEALTH = 0xD5 # OFFSET_ARMOR = 0xB8 OFFSET_HEALTH = 0x354 # 正确 OFFSET_ARMOR = 0x358 # 正确(护甲紧挨着生命) OFFSET_MONEY = 0x0054ADC8 OFFSET_WANTED = 0x00549788 PM = None BASE_ADDR = 0 PROCESS_NAME = "gta-vc.exe" def attach_game(): global PM, BASE_ADDR try: PM = pymem.Pymem(PROCESS_NAME) module = pymem.process.module_from_name(PM.process_handle, PROCESS_NAME) BASE_ADDR = module.lpBaseOfDll messagebox.showinfo("成功", "已附加 gta-vc.exe!") status_label.config(text="✅ 已连接游戏") except pymem.exception.ProcessNotFound: messagebox.showerror("错误", "未找到 gta-vc.exe\n请先启动罪恶都市!") status_label.config(text="❌ 未找到游戏") PM = None BASE_ADDR = 0 except Exception as e: messagebox.showerror("异常", f"附加失败:{str(e)}") status_label.config(text="❌ 连接失败") PM = None BASE_ADDR = 0 def get_player_ptr(): global PM, BASE_ADDR if PM is None or BASE_ADDR ==0: return 0 try: return PM.read_int(BASE_ADDR + OFFSET_PLAYER_PTR) except: return 0 def set_health(): global PM if PM is None: messagebox.showwarning("提示", "请先附加游戏!") return player_ptr = get_player_ptr() if player_ptr == 0: messagebox.showerror("错误", "读取玩家指针失败!偏移/版本不匹配!") return try: val = float(health_entry.get()) PM.write_float(player_ptr + OFFSET_HEALTH, val) except ValueError: messagebox.showerror("错误", "请输入数字!") def set_armor(): global PM if PM is None: messagebox.showwarning("提示", "请先附加游戏!") return player_ptr = get_player_ptr() if player_ptr == 0: messagebox.showerror("错误", "读取玩家指针失败!偏移/版本不匹配!") return try: val = float(armor_entry.get()) PM.write_float(player_ptr + OFFSET_ARMOR, val) except ValueError: messagebox.showerror("错误", "请输入数字!") def set_money(): global PM, BASE_ADDR if PM is None: messagebox.showwarning("提示", "请先附加游戏!") return if BASE_ADDR ==0: messagebox.showerror("错误","模块基址获取失败") return try: val = int(money_entry.get()) PM.write_int(BASE_ADDR + OFFSET_MONEY, val) except ValueError: messagebox.showerror("错误", "请输入数字!") def set_wanted(): global PM, BASE_ADDR if PM is None: messagebox.showwarning("提示", "请先附加游戏!") return if BASE_ADDR ==0: messagebox.showerror("错误","模块基址获取失败") return try: val = int(wanted_entry.get()) if val < 0 or val > 6: messagebox.showwarning("提示", "通缉等级范围0~6") return PM.write_int(BASE_ADDR + OFFSET_WANTED, val) except ValueError: messagebox.showerror("错误", "请输入数字!") def loop_refresh_info(): global PM, BASE_ADDR while True: if PM is not None and BASE_ADDR !=0: try: player_ptr = PM.read_int(BASE_ADDR + OFFSET_PLAYER_PTR) if player_ptr != 0: hp = PM.read_float(player_ptr + OFFSET_HEALTH) ar = PM.read_float(player_ptr + OFFSET_ARMOR) else: hp = 0 ar = 0 mon = PM.read_int(BASE_ADDR + OFFSET_MONEY) want = PM.read_int(BASE_ADDR + OFFSET_WANTED) root.after(0, lambda: health_var.set(f"{hp:.1f}")) root.after(0, lambda: armor_var.set(f"{ar:.1f}")) root.after(0, lambda: money_var.set(str(mon))) root.after(0, lambda: wanted_var.set(str(want))) except Exception as e: root.after(0, lambda: health_var.set("读取失败")) root.after(0, lambda: armor_var.set("读取失败")) root.after(0, lambda: money_var.set("读取失败")) root.after(0, lambda: wanted_var.set("读取失败")) # 这里不再自动置空PM,防止状态错乱 # PM = None # root.after(0, lambda: status_label.config(text="❌ 游戏断开")) time.sleep(0.3) # 冻结生命线程 def freeze_loop(): global PM while True: if freeze_var.get() and PM is not None and BASE_ADDR !=0: try: player_ptr = get_player_ptr() if player_ptr != 0: PM.write_float(player_ptr + OFFSET_HEALTH, float(health_entry.get())) except: pass time.sleep(0.1) # ===================== GUI ===================== root = tk.Tk() root.title("GTA罪恶都市 修改器【学习演示】") root.geometry("440x340") health_var = tk.StringVar(value="---") armor_var = tk.StringVar(value="---") money_var = tk.StringVar(value="---") wanted_var = tk.StringVar(value="---") status_label = ttk.Label(root, text="❌ 未连接游戏", font=("Consolas",11)) status_label.pack(pady=5) attach_btn = ttk.Button(root, text="1.附加游戏进程", command=attach_game) attach_btn.pack(pady=3) frame = ttk.Frame(root) frame.pack(pady=10, fill="x", padx=20) ttk.Label(frame, text="生命值:").grid(row=0, column=0, sticky="w") health_entry = ttk.Entry(frame, width=12) health_entry.grid(row=0, column=1, padx=5) health_entry.insert(0, "200.0") ttk.Button(frame, text="写入", command=set_health).grid(row=0, column=2, padx=2) ttk.Label(frame, text="当前:").grid(row=0, column=3, padx=3) ttk.Label(frame, textvariable=health_var).grid(row=0, column=4) ttk.Label(frame, text="护 甲:").grid(row=1, column=0, sticky="w") armor_entry = ttk.Entry(frame, width=12) armor_entry.grid(row=1, column=1, padx=5) armor_entry.insert(0, "200.0") ttk.Button(frame, text="写入", command=set_armor).grid(row=1, column=2, padx=2) ttk.Label(frame, text="当前:").grid(row=1, column=3, padx=3) ttk.Label(frame, textvariable=armor_var).grid(row=1, column=4) ttk.Label(frame, text="金 钱:").grid(row=2, column=0, sticky="w") money_entry = ttk.Entry(frame, width=12) money_entry.grid(row=2, column=1, padx=5) money_entry.insert(0, "9999999") ttk.Button(frame, text="写入", command=set_money).grid(row=2, column=2, padx=2) ttk.Label(frame, text="当前:").grid(row=2, column=3, padx=3) ttk.Label(frame, textvariable=money_var).grid(row=2, column=4) ttk.Label(frame, text="通缉星:").grid(row=3, column=0, sticky="w") wanted_entry = ttk.Entry(frame, width=12) wanted_entry.grid(row=3, column=1, padx=5) wanted_entry.insert(0, "0") ttk.Button(frame, text="写入", command=set_wanted).grid(row=3, column=2, padx=2) ttk.Label(frame, text="当前:").grid(row=3, column=3, padx=3) ttk.Label(frame, textvariable=wanted_var).grid(row=3, column=4) freeze_var = tk.BooleanVar() freeze_check = ttk.Checkbutton(root, text="冻结生命(不掉血)", variable=freeze_var) freeze_check.pack() read_thread = threading.Thread(target=loop_refresh_info, daemon=True) read_thread.start() freeze_thread = threading.Thread(target=freeze_loop, daemon=True) freeze_thread.start() root.mainloop()python语言-《侠盗猎车:罪恶都市》中文版-金钱-生命-护甲-修改器代码-QZQ
张小明
前端开发工程师
DevExpress VCL 26.1.3 在 Delphi 13.1 上的安装与部署指南
简介:这套DevExpress VCL Controls 26.1.3 EN版本专门面向使用Embarcadero Delphi 13.1(RAD Studio 13.1,代号Alexandria)的Windows原生应用开发者,覆盖数据网格、报表引擎、图表、富文本编辑器、Office风格Ribbon、仪…
硬件在环仿真HIL全解析:从架构搭建到工程落地实践
做嵌入式控制或者车辆电控的人,一定绕不开“测试怎么才能更接近真实”这个死结。纯软件仿真便宜、灵活,但模型毕竟是在PC上跑,传感器、执行器、线束、通信延迟统统被理想化了;直接拿样车、样机做实测,结果最可信&#…
Claude Code 使用教程:用 CLAUDE.md 与 Plan 模式搭建可复现的 Skill 工作流
/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …
Dbsyncer实战:MySQL全量同步与增量同步配置指南
Dbsyncer这个开源数据同步中间件,最近在圈子里聊得不少。简单说,它是一个带Web管理界面的数据同步工具,不写代码、不装客户端,浏览器里点点点就能把MySQL的数据同步到另一个MySQL或者其他数据库。我这次带大家玩一下最常见的场景&…
Hermes Agent 与 Harness 区别:自主 AI Agent 与 DevOps 平台如何各司其职
/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …
2026年OpenClaw部署避坑指南:腾讯云+百炼Coding Plan 7分钟跑通TaoToken
/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …