#!/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, PERKS, PETS, FLASHLIGHTS, EMOTES, OUTFITS, 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), ("Perks", PERKS), ("Pets", PETS), ("Flashlights", FLASHLIGHTS), ("Emotes", EMOTES), ("Outfits", OUTFITS)]: 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: key_map={"Robes":("robeOverrides","unlockRobes"),"Characters":("characterOverrides","unlockCharacters"),"Perks":("perkOverrides","unlockPerks"),"Pets":("petOverrides","unlockPets"),"Flashlights":("flashlightOverrides","unlockFlashlights"),"Emotes":("emoteOverrides","unlockEmotes"),"Outfits":("outfitOverrides","unlockOutfits")} k, g = key_map[title] cur = self.cfg.get(k, {}).get(name, self.cfg.get(g, 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): def compress(title, items, k, g): over = {n: self.vars[(title,n)].get() for n in items} if all(over.values()): self.cfg[g]=True; self.cfg.pop(k,None) elif not any(over.values()): self.cfg[g]=False; self.cfg.pop(k,None) else: self.cfg[k]=over; self.cfg[g]=True compress("Robes", ROBES, "robeOverrides", "unlockRobes") compress("Characters", CHARS, "characterOverrides", "unlockCharacters") compress("Perks", PERKS, "perkOverrides", "unlockPerks") compress("Pets", PETS, "petOverrides", "unlockPets") compress("Flashlights", FLASHLIGHTS, "flashlightOverrides", "unlockFlashlights") compress("Emotes", EMOTES, "emoteOverrides", "unlockEmotes") compress("Outfits", OUTFITS, "outfitOverrides", "unlockOutfits") 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()