Skip to content

Commit

Permalink
v1.67 final
Browse files Browse the repository at this point in the history
  • Loading branch information
Ariescyn committed Mar 8, 2023
1 parent be089e0 commit fd81d23
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 50 deletions.
153 changes: 137 additions & 16 deletions SaveManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import subprocess, os, zipfile, requests, re, time, hexedit, webbrowser, itemdata, lzma, datetime, json
from os_layer import *
from pathlib import Path as PATH
#Collapse all functions to navigate. In Atom editor: "crtl + ALT + ] To Close"
#Collapse all functions to navigate. In Atom editor: "Edit > Folding > Fold All"



Expand Down Expand Up @@ -106,7 +106,7 @@ def run_func(arg):
parent_window = root
popupwin = Toplevel(parent_window)
popupwin.title(title)
# popupwin.geometry("200x75")

lab = Label(popupwin, text=text)
lab.grid(row=0, column=0, padx=5, pady=5, columnspan=2)
# Places popup window at center of the root window
Expand Down Expand Up @@ -1035,7 +1035,8 @@ def get_char_stats():
try:
stats = hexedit.get_stats(file, char_slot)[0]
except Exception as e:
pop_up("Can't get stats, go in-game and\nload into the character first or try leveling up once.")
#pop_up("Can't get stats, go in-game and\nload into the character first or try leveling up once.")
popup("Unable to aquire stats/level.\nYour character level may be incorrect.\nFix now?",functions=(lambda:fix_stats_menu(file, char_slot), lambda:popupwin.destroy()), buttons=True, button_names=("Yes", "No"), parent_window=popupwin)
return

# entries = [vig_ent, min_ent, end_ent, str_ent, dex_ent, int_ent, fai_ent, arc_ent]
Expand Down Expand Up @@ -2383,22 +2384,23 @@ def run_cheat():
hexedit.set_attributes(dest_file, char_ind, [99, 99, 99], cheat=True)
popup("Success!", parent_window=popupwin)
except Exception as e:
traceback.print_exc()
str_err = "".join(traceback.format_exc())
popup(str_err, parent_window=popupwin)
#traceback.print_exc()
#str_err = "".join(traceback.format_exc())
#popup(str_err, parent_window=popupwin)
popup("Unable to aquire stats/level.\nYour character level may be incorrect.\nFix now?",functions=(lambda:fix_stats_menu(dest_file, char_ind), lambda:popupwin.destroy()), buttons=True, button_names=("Yes", "No"), parent_window=popupwin)



popupwin = Toplevel(root)
popupwin.title("God Mode")
popupwin.resizable(width=True, height=True)
popupwin.geometry("450x450")
popupwin.geometry("510x470")

x = root.winfo_x()
y = root.winfo_y()
popupwin.geometry("+%d+%d" % (x + 200, y + 200))

main_label = Label(popupwin, text="DO NOT use this feature online! You will most certainly get banned.\n\nThis will set your HP,ST,FP to 60,000\n\n Note: After leveling up, your stats will return to normal\n\nNote: This won't work for some save files, like Nexus Tarnished")
main_label = Label(popupwin, text="DO NOT use this feature online! You will most certainly get banned.\n\nThis will set your HP,ST,FP to 60,000\n\n Note: Your stats will return to normal after leveling up or equipping a stat boosting item. \n\nNote: Remove any stat boosting gear from your character before doing this or it won't work.\n\n")
# main_label.grid(row=0)
main_label.pack()
# MAIN SAVE FILE LISTBOX
Expand Down Expand Up @@ -2432,6 +2434,124 @@ def run_cheat():
but_set.pack()


def fix_stats_menu(dest_file, char_ind):
def validate(P):
if len(P) == 0:
return True
elif len(P) < 3 and P.isdigit() and int(P) > 0:
return True
else:
# Anything else, reject it
return False

def fix():
for entry in entries:
if len(entry.get()) < 1:
popup("Not all stats entered!",parent_window=popupwin)
return

stat_lst = [int(i.get()) for i in entries]

name = dest_file.split("/")[-2]
print(f"DEST: {dest_file} == char_ind {char_ind} --- {stat_lst}")
archive_file(dest_file, name, "ACTION: Fix Level", get_charnames(dest_file))
x = hexedit.fix_stats(dest_file, char_ind, stat_lst)
if x is True:
popup("Successfully found stats and patched level!", parent_window=popupwin)
elif x is False:
popup("Unable to find stats, ensure you entered your stats correctly.\nMake sure your stats aren't boosted by an item.", parent_window=popupwin)
return


# Main GUI content STAT
popupwin = Toplevel(root)
popupwin.title("Fix Level")
popupwin.resizable(width=True, height=True)
popupwin.geometry("580x550")
vcmd = (popupwin.register(validate), "%P")
bolded = FNT.Font(weight="bold") # will use the default font
x = root.winfo_x()
y = root.winfo_y()
popupwin.geometry("+%d+%d" % (x + 200, y + 200))



main_label = Label(popupwin, text="Enter your character stats.\n\nGo in-game and remove any stat boosting gear and take note of your stats and enter them here:")
main_label.grid(row=0, column=0, padx=(20,0), pady=(5,0), sticky="n")

# VIGOR
vig_lab = Label(popupwin, text="VIGOR:")
vig_lab.config(font=bolded)
vig_lab.grid(row=0, column=0, padx=(20, 0), pady=(75, 0), sticky="n")

vig_ent = Entry( popupwin, borderwidth=5, width=3, validate="key", validatecommand=vcmd)
vig_ent.grid(row=0, column=0, padx=(120, 0), pady=(75, 0), sticky="n")

# MIND
min_lab = Label(popupwin, text="MIND:")
min_lab.config(font=bolded)
min_lab.grid(row=0, column=0, padx=(20, 0), pady=(115, 0), sticky="n")

min_ent = Entry(popupwin, borderwidth=5, width=3, validate="key", validatecommand=vcmd)
min_ent.grid(row=0, column=0, padx=(120, 0), pady=(115, 0), sticky="n")

# ENDURANCE
end_lab = Label(popupwin, text="END:")
end_lab.config(font=bolded)
end_lab.grid(row=0, column=0, padx=(20, 0), pady=(155, 0), sticky="n")

end_ent = Entry(popupwin, borderwidth=5, width=3, validate="key", validatecommand=vcmd)
end_ent.grid(row=0, column=0, padx=(120, 0), pady=(155, 0), sticky="n")

# STRENGTH
str_lab = Label(popupwin, text="STR:")
str_lab.config(font=bolded)
str_lab.grid(row=0, column=0, padx=(20, 0), pady=(195, 0), sticky="n")

str_ent = Entry(popupwin, borderwidth=5, width=3, validate="key", validatecommand=vcmd)
str_ent.grid(row=0, column=0, padx=(120, 0), pady=(195, 0), sticky="n")

# DEXTERITY
dex_lab = Label(popupwin, text="DEX:")
dex_lab.config(font=bolded)
dex_lab.grid(row=0, column=0, padx=(20, 0), pady=(235, 0), sticky="n")

dex_ent = Entry(popupwin, borderwidth=5, width=3, validate="key", validatecommand=vcmd)
dex_ent.grid(row=0, column=0, padx=(120, 0), pady=(235, 0), sticky="n")

# INTELLIGENCE
int_lab = Label(popupwin, text="INT:")
int_lab.config(font=bolded)
int_lab.grid(row=0, column=0, padx=(20, 0), pady=(275, 0), sticky="n")

int_ent = Entry(popupwin, borderwidth=5, width=3, validate="key", validatecommand=vcmd)
int_ent.grid(row=0, column=0, padx=(120, 0), pady=(275, 0), sticky="n")

# FAITH
fai_lab = Label(popupwin, text="FAITH:")
fai_lab.config(font=bolded)
fai_lab.grid(row=0, column=0, padx=(20, 0), pady=(315, 0), sticky="n")

fai_ent = Entry(popupwin, borderwidth=5, width=3, validate="key", validatecommand=vcmd)
fai_ent.grid(row=0, column=0, padx=(120, 0), pady=(315, 0), sticky="n")

# ARCANE
arc_lab = Label(popupwin, text="ARC:")
arc_lab.config(font=bolded)
arc_lab.grid(row=0, column=0, padx=(20, 0), pady=(355, 0), sticky="n")

arc_ent = Entry(popupwin, borderwidth=5, width=3, validate="key", validatecommand=vcmd)
arc_ent.grid(row=0, column=0, padx=(120, 0), pady=(355, 0), sticky="n")

# lIST OF ALL ENTRIES
entries = [vig_ent, min_ent, end_ent, str_ent, dex_ent, int_ent, fai_ent, arc_ent]



# SET STATS BUTTON
but_set_stats = Button(popupwin, text="Fix", width=12, command=fix)
but_set_stats.config(font=bolded)
but_set_stats.grid(row=0, column=0, padx=(25, 0), pady=(420, 0), sticky="n")



Expand Down Expand Up @@ -2510,6 +2630,15 @@ def about():
popup(text="Author: Lance Fitz\nEmail: [email protected]\nGithub: github.com/Ariescyn")


def open_notes():
name = fetch_listbox_entry(lb)[0]
if len(name) < 1:
popup("No listbox item selected.")
return
cmd = lambda: open_textfile_in_editor(f"{savedir}{name}/notes.txt")
out = run_command(cmd)





Expand Down Expand Up @@ -2631,14 +2760,6 @@ def do_popup(event):
rt_click_menu.grab_release()


def open_notes():
name = fetch_listbox_entry(lb)[0]
if len(name) < 1:
popup("No listbox item selected.")
return
cmd = lambda: open_textfile_in_editor(f"{savedir}{name}/notes.txt")
out = run_command(cmd)


rt_click_menu = Menu(lb, tearoff=0)
#rt_click_menu.add_command(label="Edit Notes", command=open_notes)
Expand Down
3 changes: 1 addition & 2 deletions data/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
New God Mode cheat (Sets your Health, Stamina, FP to 60,000)
Fixed bug with renaming characters that contain the same substring
God mode fix (read the new description in god-mode window)
Minor bug fixes and improvements
86 changes: 56 additions & 30 deletions hexedit.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def recalc_checksum(file):
with open(file, "wb") as fh1:
fh1.write(dat)


def change_name(file, nw_nm, dest_slot):
"""Builds list of each character name from static name locations in header, then passes specified char name in bytes into replacer function."""

Expand Down Expand Up @@ -112,6 +113,7 @@ def replacer(file, old_name, name):
x = replacer(file, name_locations[dest_slot - 1], nw_nm)
return x


def replace_id(file, newid):
id_loc = []
index = 0
Expand Down Expand Up @@ -377,7 +379,7 @@ def get_stats(file, char_slot):
l_endian(slot1[ind + 24 : ind + 25]),
l_endian(slot1[ind + 28 : ind + 29]),
]
hp = l_endian(slot1[ind - 44 : ind - 40])


if sum(stats) == lv + 79 and l_endian(slot1[ind + 44 : ind + 46]) == lv:
start_ind = ind
Expand Down Expand Up @@ -420,7 +422,9 @@ def get_stats(file, char_slot):
stam.append(l_endian(slot1[z : z + 2]))
stam_inds.append(z)
z += 4

print(f"HP: {hp}")
print(f"STAM: {stam}")
print(f"FP: {fp}")
return [
stats,
indexes,
Expand All @@ -429,22 +433,6 @@ def get_stats(file, char_slot):
fp_inds,
] # [[36, 16, 38, 33, 16, 9, 10, 7], 47421]

# DELETE THIS ON NEXT RELEASE
hp = []
hp_inds = []
x = start_ind - 44
for i in range(3):
hp.append(l_endian(slot1[x : x + 2]))
hp_inds.append(x)
x += 4

return [
stats,
indexes,
hp_inds,
] # [[36, 16, 38, 33, 16, 9, 10, 7], [47421,47421], [3534345,35345,35345]]
# END


def set_level(file, char, lvl):
"""Sets levels in static header position by char names for in-game load save menu."""
Expand Down Expand Up @@ -485,7 +473,6 @@ def get_levels(file):
ind += 588
return lvls


def set_attributes(file, slot, lvls, cheat=False):

stats = get_stats(file, slot)
Expand Down Expand Up @@ -522,7 +509,6 @@ def set_attributes(file, slot, lvls, cheat=False):
f.write(dat)
recalc_checksum(file)


def additem(file, slot, itemids, quantity):
cs = get_slot_ls(file)[slot - 1]
slices = get_slot_slices(file)
Expand Down Expand Up @@ -617,7 +603,6 @@ def search_itemid(f1,f2,f3,q1,q2,q3):
return None



def set_play_time(file,slot,time):
# time = [hr,min,sec]
time = [int(i) for i in time]
Expand Down Expand Up @@ -645,7 +630,6 @@ def set_play_time(file,slot,time):
recalc_checksum(file)



def set_starting_class(file, slot, char_class):
cs = get_slot_ls(file)[slot - 1]
slices = get_slot_slices(file)
Expand Down Expand Up @@ -674,8 +658,6 @@ def set_starting_class(file, slot, char_class):
return True




def find_inventory(file,slot,ids):
with open(file, 'rb') as f:
dat = f.read()
Expand All @@ -696,8 +678,6 @@ def find_inventory(file,slot,ids):
return index




def get_inventory(file, slot):
items = dict([(f"{v[0]}:{v[1]}",k) for k,v in itemdict.items()])
with open(file, "rb") as f:
Expand Down Expand Up @@ -739,10 +719,6 @@ def get_inventory(file, slot):
return finished_ls






def overwrite_item(file,slot, item_dict_entry, newids):
#entry = {'name': 'Smithing Stone :[8]', 'item_id': [123, 39], 'uid': [0, 176], 'quantity': 63, 'pad1': [0, 0, 0], 'iter': 103, 'pad2': [58, 0, 0], 'index': 63987}

Expand All @@ -759,3 +735,53 @@ def overwrite_item(file,slot, item_dict_entry, newids):
pos += 1

recalc_checksum(file)


def fix_stats(file, char_slot, stat_list):


slots = get_slot_ls(file)
slot_slices = get_slot_slices(file)

start_ind = 0
slot1 = slots[char_slot - 1]
indexes = []
lvl_ind = 0
for ind, b in enumerate(slot1):
if ind > 90000:
break

stats = [
l_endian(slot1[ind : ind + 1]),
l_endian(slot1[ind + 4 : ind + 5]),
l_endian(slot1[ind + 8 : ind + 9]),
l_endian(slot1[ind + 12 : ind + 13]),
l_endian(slot1[ind + 16 : ind + 17]),
l_endian(slot1[ind + 20 : ind + 21]),
l_endian(slot1[ind + 24 : ind + 25]),
l_endian(slot1[ind + 28 : ind + 29]),
]


if stats == stat_list:
lvl_ind = ind + 44
break


if lvl_ind == 0:
return False

new_lv = sum(stats) - 79
new_lv_bytes = new_lv.to_bytes(2, "little")
data = (
slot_slices[char_slot - 1][0]
+ slot1[:lvl_ind]
+ new_lv_bytes
+ slot1[lvl_ind + 2 :]
+ slot_slices[char_slot - 1][1]
)

with open(file, "wb") as fh:
fh.write(data)
set_level(file, char_slot, new_lv) # Set level runs recalc_checksum
return True
Loading

0 comments on commit fd81d23

Please sign in to comment.