#!/usr/bin/env python3 """Tkinter GUI for standalone — selective checkboxes, writes DevourUnlocker.json""" import tkinter as tk from tkinter import ttk, messagebox import json, pathlib from devour_unlocker import ROBES, CHARS, default_json_path, load_config, save_config class App(tk.Tk): def __init__(self): super().__init__() self.title("DevourUnlocker — Selective Unlock") self.geometry("560x680") self.json_path = default_json_path() self.cfg = load_config(str(self.json_path)) self.vars = {} self._build() def _build(self): ttk.Label(self, text="DevourUnlocker v2 — Standalone (multiplayer safe)").pack(pady=6) ttk.Label(self, text=f"Config: {self.json_path}").pack() btn_row = ttk.Frame(self); btn_row.pack(pady=6) ttk.Button(btn_row, text="Unlock All", command=self.unlock_all).pack(side=tk.LEFT, padx=4) ttk.Button(btn_row, text="Lock All", command=self.lock_all).pack(side=tk.LEFT, padx=4) ttk.Button(btn_row, text="Save", command=self.save).pack(side=tk.LEFT, padx=4) ttk.Button(btn_row, text="Reload", command=self.reload).pack(side=tk.LEFT, padx=4) nb = ttk.Notebook(self); nb.pack(fill=tk.BOTH, expand=True, padx=8, pady=8) for title, items in [("Robes", ROBES), ("Characters", CHARS)]: f = ttk.Frame(nb) nb.add(f, text=title) canvas = tk.Canvas(f) scroll = ttk.Scrollbar(f, command=canvas.yview) inner = ttk.Frame(canvas) inner.bind("", lambda e, c=canvas: c.configure(scrollregion=c.bbox("all"))) canvas.create_window((0,0), window=inner, anchor="nw") canvas.configure(yscrollcommand=scroll.set) canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) scroll.pack(side=tk.RIGHT, fill=tk.Y) for name in items: cur = self.cfg.get("robeOverrides" if title=="Robes" else "characterOverrides", {}).get(name, self.cfg.get("unlockRobes" if title=="Robes" else "unlockCharacters", True)) var = tk.BooleanVar(value=bool(cur)) self.vars[(title,name)] = var ttk.Checkbutton(inner, text=name, variable=var).pack(anchor="w", padx=8, pady=2) def unlock_all(self): for v in self.vars.values(): v.set(True) def lock_all(self): for v in self.vars.values(): v.set(False) def reload(self): self.cfg = load_config(str(self.json_path)) self.destroy(); self.__init__() def save(self): robe_over = {n: self.vars[("Robes",n)].get() for n in ROBES} char_over = {n: self.vars[("Characters",n)].get() for n in CHARS} # compress: if all same, use global all_r = all(robe_over.values()); none_r = not any(robe_over.values()) if all_r: self.cfg["unlockRobes"]=True; self.cfg.pop("robeOverrides",None) elif none_r: self.cfg["unlockRobes"]=False; self.cfg.pop("robeOverrides",None) else: self.cfg["robeOverrides"]=robe_over; self.cfg["unlockRobes"]=True all_c = all(char_over.values()); none_c = not any(char_over.values()) if all_c: self.cfg["unlockCharacters"]=True; self.cfg.pop("characterOverrides",None) elif none_c: self.cfg["unlockCharacters"]=False; self.cfg.pop("characterOverrides",None) else: self.cfg["characterOverrides"]=char_over; self.cfg["unlockCharacters"]=True save_config(str(self.json_path), self.cfg) messagebox.showinfo("Saved", f"Wrote {self.json_path}\nLaunch Devour with winhttp.dll enabled.") if __name__ == "__main__": App().mainloop()