Загрузка данных
import pymem
import time
import json
import os
import psutil
from tkinter import Tk, Label, Entry, Button, StringVar, messagebox
CONFIG_FILE = "config.json"
DEFAULT_CONFIG = {
"old_skin_id": 33602,
"new_skin_id": 97100,
"process_name": "HD-Player.exe",
"scan_delay": 1.5
}
class Standoff2SkinChanger:
def __init__(self):
self.pm = None
self.config = self.load_config()
self.old_id = self.config["old_skin_id"]
self.new_id = self.config["new_skin_id"]
self.process_name = self.config["process_name"]
def load_config(self):
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, 'r') as f:
return json.load(f)
else:
with open(CONFIG_FILE, 'w') as f:
json.dump(DEFAULT_CONFIG, f, indent=4)
return DEFAULT_CONFIG.copy()
def find_bluestacks_pid(self):
for proc in psutil.process_iter(['pid', 'name']):
if proc.info['name'] == self.process_name:
return proc.info['pid']
return None
def attach_to_process(self):
pid = self.find_bluestacks_pid()
if not pid:
return False, "Bluestacks не запущен или процесс не найден"
try:
self.pm = pymem.Pymem(pid)
return True, "Подключено к Bluestacks"
except Exception as e:
return False, f"Ошибка подключения: {e}"
def find_skin_addresses(self):
if not self.pm:
return []
addresses = []
old_id_bytes = self.old_id.to_bytes(4, 'little')
start_addr = 0x01000000
end_addr = 0x7FFFFFFF
chunk_size = 0x100000
for current_addr in range(start_addr, end_addr, chunk_size):
try:
chunk = self.pm.read_bytes(current_addr, chunk_size)
pos = chunk.find(old_id_bytes)
while pos != -1:
addr = current_addr + pos
try:
value = self.pm.read_int(addr)
if value == self.old_id:
addresses.append(addr)
except:
pass
pos = chunk.find(old_id_bytes, pos + 1)
except:
continue
return addresses
def replace_skins(self):
if not self.pm:
return False, "Не подключено к процессу"
addresses = self.find_skin_addresses()
if not addresses:
return False, "Скины не найдены в памяти"
replaced = 0
for addr in addresses:
try:
self.pm.write_int(addr, self.new_id)
replaced += 1
except:
continue
return True, f"Заменено {replaced} скинов"
def run(self, status_callback=None):
if status_callback:
status_callback("Поиск процесса Bluestacks...")
success, msg = self.attach_to_process()
if not success:
return False, msg
if status_callback:
status_callback("Поиск скинов в памяти...")
time.sleep(self.config["scan_delay"])
success, msg = self.replace_skins()
return success, msg
class SkinChangerGUI:
def __init__(self):
self.root = Tk()
self.root.title("Standoff 2 Skin Changer v1.0")
self.root.geometry("400x250")
self.root.resizable(False, False)
self.changer = Standoff2SkinChanger()
self.status_var = StringVar()
self.status_var.set("Готов к работе")
self.create_widgets()
def create_widgets(self):
Label(self.root, text="Standoff 2 Skin Changer", font=("Arial", 14, "bold")).pack(pady=10)
Label(self.root, text=f"Замена: {self.changer.old_id} → {self.changer.new_id}", font=("Arial", 10)).pack()
Label(self.root, text="Старый ID:").pack()
self.old_entry = Entry(self.root, width=15)
self.old_entry.insert(0, str(self.changer.old_id))
self.old_entry.pack()
Label(self.root, text="Новый ID:").pack()
self.new_entry = Entry(self.root, width=15)
self.new_entry.insert(0, str(self.changer.new_id))
self.new_entry.pack()
Button(self.root, text="Обновить настройки", command=self.update_config).pack(pady=5)
Button(self.root, text="ЗАМЕНИТЬ СКИНЫ", command=self.execute, bg="green", fg="white", font=("Arial", 12, "bold")).pack(pady=10)
Label(self.root, textvariable=self.status_var, fg="blue").pack(pady=5)
def update_config(self):
try:
old = int(self.old_entry.get())
new = int(self.new_entry.get())
self.changer.old_id = old
self.changer.new_id = new
self.changer.config["old_skin_id"] = old
self.changer.config["new_skin_id"] = new
with open(CONFIG_FILE, 'w') as f:
json.dump(self.changer.config, f, indent=4)
self.status_var.set(f"Обновлено: {old} → {new}")
except:
self.status_var.set("Ошибка: введите числа")
def execute(self):
self.status_var.set("Идет замена...")
self.root.update()
success, msg = self.changer.run(lambda s: self.status_var.set(s))
if success:
messagebox.showinfo("Успешно", msg)
self.status_var.set(f"Готово! {msg}")
else:
messagebox.showerror("Ошибка", msg)
self.status_var.set("Ошибка выполнения")
def run(self):
self.root.mainloop()
if __name__ == "__main__":
app = SkinChangerGUI()
app.run()