Titan Quest Android Save | Editor
def show_info(self): name_offset = 0x04 name = self.get_string(name_offset) level = self.get_int(0x44) gold = self.get_int(0x4C) skill_pts = self.get_int(0x64) attr_pts = self.get_int(0x68) print(f"Name: name") print(f"Level: level") print(f"Gold: gold") print(f"Skill Points: skill_pts") print(f"Attribute Points: attr_pts") if name == " main ": # Change this to your actual save path save_path = "/storage/emulated/0/Android/data/com.handygames.titanquestlegends/files/SaveData/Character1.que"
self.filepath = None self.data = None # Widgets tk.Button(root, text="Open Save File (.que)", command=self.open_file).pack(pady=10) self.info_frame = tk.LabelFrame(root, text="Character Info") self.info_frame.pack(fill="x", padx=10, pady=5) self.stats_frame = tk.LabelFrame(root, text="Edit Stats") self.stats_frame.pack(fill="both", expand=True, padx=10, pady=5) # Labels for info self.name_label = tk.Label(self.info_frame, text="Name: --") self.name_label.pack(anchor="w") self.level_label = tk.Label(self.info_frame, text="Level: --") self.level_label.pack(anchor="w") self.gold_label = tk.Label(self.info_frame, text="Gold: --") self.gold_label.pack(anchor="w") # Entry fields fields = ["Level", "Gold", "Strength", "Dexterity", "Intelligence", "Skill Points", "Attr Points"] self.entries = {} for field in fields: row = tk.Frame(self.stats_frame) row.pack(fill="x", padx=5, pady=2) tk.Label(row, text=field, width=15, anchor="w").pack(side="left") entry = tk.Entry(row) entry.pack(side="right", expand=True, fill="x") self.entries[field] = entry tk.Button(root, text="Apply Changes", command=self.apply_changes, bg="green", fg="white").pack(pady=10) tk.Button(root, text="Save File", command=self.save_file, bg="blue", fg="white").pack(pady=5) def open_file(self): path = filedialog.askopenfilename(filetypes=[("Titan Quest Save", "*.que")]) if not path: return self.filepath = path self.load_save() def load_save(self): try: with open(self.filepath, 'rb') as f: self.data = bytearray(f.read()) self.show_info() messagebox.showinfo("Success", "Save loaded successfully") except Exception as e: messagebox.showerror("Error", f"Failed to load: e")
import struct import os import shutil from pathlib import Path class TitanQuestSaveEditor: def (self, filepath): self.filepath = Path(filepath) self.data = None self.backup_path = None
print("=== CURRENT STATS ===") editor.show_info() Titan Quest Android Save Editor
def apply_changes(self): if self.data is None: messagebox.showwarning("No file", "Open a save file first") return try: self.set_int(0x44, self.entries["Level"].get()) self.set_int(0x4C, self.entries["Gold"].get()) self.set_int(0x50, self.entries["Strength"].get()) self.set_int(0x54, self.entries["Dexterity"].get()) self.set_int(0x58, self.entries["Intelligence"].get()) self.set_int(0x64, self.entries["Skill Points"].get()) self.set_int(0x68, self.entries["Attr Points"].get()) messagebox.showinfo("Applied", "Changes applied in memory. Click Save File to write.") except ValueError: messagebox.showerror("Error", "Please enter valid numbers")
import tkinter as tk from tkinter import filedialog, messagebox, ttk import struct import shutil import os class TQSaveEditorGUI: def (self, root): self.root = root self.root.title("Titan Quest Android Save Editor") self.root.geometry("500x600")
def get_int(self, offset): return struct.unpack('<I', self.data[offset:offset+4])[0] def show_info(self): name_offset = 0x04 name = self
def show_info(self): name = self.get_string(0x04) level = self.get_int(0x44) gold = self.get_int(0x4C) self.name_label.config(text=f"Name: name") self.level_label.config(text=f"Level: level") self.gold_label.config(text=f"Gold: gold") # Populate entries with current values self.entries["Level"].delete(0, tk.END) self.entries["Level"].insert(0, str(level)) self.entries["Gold"].delete(0, tk.END) self.entries["Gold"].insert(0, str(gold)) self.entries["Strength"].delete(0, tk.END) self.entries["Strength"].insert(0, str(self.get_int(0x50))) self.entries["Dexterity"].delete(0, tk.END) self.entries["Dexterity"].insert(0, str(self.get_int(0x54))) self.entries["Intelligence"].delete(0, tk.END) self.entries["Intelligence"].insert(0, str(self.get_int(0x58))) self.entries["Skill Points"].delete(0, tk.END) self.entries["Skill Points"].insert(0, str(self.get_int(0x64))) self.entries["Attr Points"].delete(0, tk.END) self.entries["Attr Points"].insert(0, str(self.get_int(0x68)))
def load(self): with open(self.filepath, 'rb') as f: self.data = bytearray(f.read())
def get_string(self, offset): end = self.data.find(b'\x00', offset) if end == -1: end = offset + 64 return self.data[offset:end].decode('utf-8', errors='ignore') text="Open Save File (.que)"
def edit_stats(self, level=None, gold=None, strength=None, dexterity=None, intelligence=None, skill_points=None, attr_points=None): # Offsets (verify with your save version) offsets = 'level': 0x44, 'exp': 0x48, 'gold': 0x4C, 'strength': 0x50, 'dexterity': 0x54, 'intelligence': 0x58, 'health': 0x5C, 'mana': 0x60, 'skill_points': 0x64, 'attr_points': 0x68 if level is not None: self.set_int(offsets['level'], level) if gold is not None: self.set_int(offsets['gold'], gold) if strength is not None: self.set_int(offsets['strength'], strength) if dexterity is not None: self.set_int(offsets['dexterity'], dexterity) if intelligence is not None: self.set_int(offsets['intelligence'], intelligence) if skill_points is not None: self.set_int(offsets['skill_points'], skill_points) if attr_points is not None: self.set_int(offsets['attr_points'], attr_points)
# Modify editor.edit_stats(gold=999999, skill_points=100, attr_points=50, level=40)