Skip to content

Instantly share code, notes, and snippets.

@Andoryuuta
Created June 11, 2020 11:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Andoryuuta/f4772f831fffb073a8a13d6c4e026da0 to your computer and use it in GitHub Desktop.
Save Andoryuuta/f4772f831fffb073a8a13d6c4e026da0 to your computer and use it in GitHub Desktop.
ACOdyssey Tweak Pack V0.8 (V1.1.4) decompiled
# uncompyle6 version 3.7.0
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)]
# Embedded file name: ACOdyssey Tweak Pack.py
import errno, os, sys, winreg, platform
from bitstring import BitStream
from bitstring import BitArray
from bitstring import ConstBitStream
from shutil import copyfile
if platform.system().lower() == 'windows':
from ctypes import windll, c_int, byref
stdout_handle = windll.kernel32.GetStdHandle(c_int(-11))
mode = c_int(0)
windll.kernel32.GetConsoleMode(c_int(stdout_handle), byref(mode))
mode = c_int(mode.value | 4)
windll.kernel32.SetConsoleMode(c_int(stdout_handle), mode)
NUM_TWEAKS = 22
CURRENT_VERSION = 'V0.8'
COMPATIBLE_VERSION = 'V1.1.4'
class cByteArrayHack:
hackName = ''
fileName = ''
status = ''
statustext = ''
originalByteArray = ''
modifiedByteArray = ''
modifiedByteArray_firstpart = ''
modifiedByteArray_secondpart = ''
byteOffset = 0
variableOffset = 0
variableType = ''
initialised = False
def __init__(self, hackName, fileName, originalByteArray, modifiedByteArray, variableOffset, variableType):
self.hackName = hackName
self.fileName = fileName
self.originalByteArray = originalByteArray
self.variableOffset = variableOffset
self.variableType = variableType
if variableOffset > 0:
temp = BitArray(modifiedByteArray)
self.modifiedByteArray_firstpart = temp[0:variableOffset * 4]
self.modifiedByteArray = modifiedByteArray
self.CheckStatus()
def CheckStatus(self):
fileStream = ConstBitStream(filename=(self.fileName))
found = fileStream.find((self.originalByteArray), bytealigned=True)
if len(found) > 1:
self.status = 'ERROR!'
return
else:
if len(found) == 1:
self.status = 'Inactive'
self.statustext = '\x1b[1;33;40mInactive\x1b[0m'
self.byteOffset = found
else:
if self.variableOffset > 0:
found = fileStream.find((self.modifiedByteArray_firstpart), bytealigned=True)
if len(found) == 1:
length = len(self.modifiedByteArray) * 4
self.modifiedByteArray = '0x' + fileStream.read(length).hex
self.status = 'Active'
if self.variableType == 'float':
self.statustext = '\x1b[1;32;40mActive\x1b[0m' + ' (%.2f)' % BitArray(self.modifiedByteArray)[self.variableOffset * 4:self.variableOffset * 4 + 32].floatle
if self.variableType == 'byte':
self.statustext = '\x1b[1;32;40mActive\x1b[0m' + ' (%u)' % BitArray(self.modifiedByteArray)[self.variableOffset * 4:self.variableOffset * 4 + 8].uint
self.byteOffset = found
else:
self.status = 'Error'
self.statustext = '\x1b[1;31;40mERROR!\x1b[0m'
else:
found = fileStream.find((self.modifiedByteArray), bytealigned=True)
if len(found) == 1:
self.status = 'Active'
self.statustext = '\x1b[1;32;40mActive\x1b[0m'
self.byteOffset = found
else:
self.status = 'Error'
self.statustext = '\x1b[1;31;40mERROR!\x1b[0m'
def Enable(self):
if self.status == 'Inactive':
print("Enabling '" + self.hackName + "'...")
fileStream = BitStream(filename=(self.fileName))
fileStream.pos = self.byteOffset[0]
fileStream.overwrite(self.modifiedByteArray)
print("\x1b[FEnabling '" + self.hackName + "'...done!")
self.Save(fileStream)
print('Checking tweak status...hang on...')
self.CheckStatus()
def Disable(self):
if self.status == 'Active':
print("Disabling '" + self.hackName + "'...")
fileStream = BitStream(filename=(self.fileName))
fileStream.pos = self.byteOffset[0]
fileStream.overwrite(self.originalByteArray)
print("\x1b[FDisabling '" + self.hackName + "'...done!")
self.Save(fileStream)
print('Checking tweak status...hang on...')
self.CheckStatus()
def Save(self, fileStream):
if self.status == 'Active' or self.status == 'Inactive':
try:
f = open(self.fileName, 'wb')
fileStream.tofile(f)
print('Updated patch written to executable: ACOdyssey.exe.')
except IOError:
print("Unable to write patch to file. Ensure the file isn't in use and try again.")
k = input('Press a key to continue...')
def WriteMenu(tweaks, backupAvailable):
active_tweaks = NumActiveTweaks(tweaks)
error_tweaks = NumErrorTweaks(tweaks)
os.system('cls')
print('====================================================================')
print('AC Odyssey Tweak Pack ' + CURRENT_VERSION + '(' + COMPATIBLE_VERSION + ')\tTotal:' + str(NUM_TWEAKS) + ' \x1b[1;32;40mActive\x1b[0m:' + str(active_tweaks) + ' \x1b[1;31;40mError\x1b[0m:' + str(error_tweaks))
print('====================================================================')
print('1. Disable Horse Speed Restriction\t\t', tweaks['horseHack'].statustext)
print('2. Custom XP Multiplier\t\t\t', tweaks['customXPMultiplier'].statustext)
print('3. Custom Enemy Health Multiplier\t\t', tweaks['customEnemyHealthMultiplier'].statustext)
print('4. Custom Enemy Damage Multiplier\t\t', tweaks['customEnemyDamageMultiplier'].statustext)
print('5. Custom Max Enemy Level Delta\t\t', tweaks['customMaxEnemyLevelDelta'].statustext)
print('6. Custom Drachmae Multiplier\t\t\t', tweaks['customDrachmaeMultiplier'].statustext)
print('7. Custom Healing : Healing Factor\t\t', tweaks['customHealingReduction1'].statustext)
print('8. Custom Healing : Reduced Health Boosts\t', tweaks['customHealingReduction2'].statustext)
print('9. Custom Resource Loot Modifier\t\t', tweaks['customResourceLootModifier'].statustext)
print('10. Animal Companion : Health Boost\t\t', tweaks['customTamedAnimalHealthBoost2'].statustext)
print('11. Animal Companion : In Combat Healing\t', tweaks['customTamedAnimalInCombatHealing'].statustext)
print('12. Animal Companion : Healing Multiplier\t', tweaks['customTamedAnimalHealingMultiplier2'].statustext)
print('--------------------------------------------------------------------')
print('R. Run Game')
if backupAvailable:
print('L. Restore Backup')
else:
print('\x1b[1;30;40mL. Restore Backup\x1b[0m')
if active_tweaks > 0:
print('D. Disable All Tweaks')
else:
print('\x1b[1;30;40mD. Disable All Tweaks\x1b[0m')
if active_tweaks == 0:
print('S. Create Backup')
else:
print('\x1b[1;30;40mS. Create Backup\x1b[0m')
print('')
print('X. Exit')
print('====================================================================')
def is_pathname_valid(pathname: str) -> bool:
"""
`True` if the passed pathname is a valid pathname for the current OS;
`False` otherwise.
"""
try:
if not isinstance(pathname, str) or not pathname:
return False
root_dirname, pathname = os.path.splitdrive(pathname)
pathname = pathname[1:len(pathname)]
root_dirname = root_dirname.rstrip(os.path.sep)
pathname_fragment = root_dirname
for pathname_part in pathname.split(os.path.sep):
pathname_fragment = pathname_fragment + os.path.sep
pathname_fragment = pathname_fragment + pathname_part
try:
os.lstat(pathname_fragment)
except OSError as exc:
if hasattr(exc, 'winerror'):
return False
if exc.errno in {errno.ENAMETOOLONG, errno.ERANGE}:
return False
except TypeError as exc:
return False
else:
return True
return False
def InitialiseTweaks():
INITIALISED_TWEAKS = 1
print('Initialising...please be patient...(%.0f%%).' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
horseHack = cByteArrayHack('Disable Horse Speed Restriction', fileName, '0x7417F30F104C2440F30F104424300F2FC17606F30F114C2430498BCF', '0xEB17F30F104C2440F30F104424300F2FC17606F30F114C2430498BCF', 0, 'bool')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customDrachmaeMultiplier = cByteArrayHack('Custom Drachmae Multiplier', fileName, '0xC333C0C3CC488B81880000004885C0741280B8D1000000007409F30F1080E8000000C3F30F1005FE5E5202C3CCCCCCCCCCCCCCCCCC', '0x9033C0C3CC488B81880000004885C0741B80B8D1000000007412C780E80000000000E03FF30F1080E8000000C3CCCCCCCCCCCCCCCC', 64, 'float')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customDrachmaeMultiplierDisableLowerBound1 = cByteArrayHack('Custom Drachmae Multiplier - Disable Lower Bound 1', fileName, '0x7208F30F11899C050000C3CCCCCCCCCCCCCCCCCCCCCCCCCCCC', '0x7200F30F11899C050000C3CCCCCCCCCCCCCCCCCCCCCCCCCCCC', 0, 'bool')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customDrachmaeMultiplierDisableLowerBound2 = cByteArrayHack('Custom Drachmae Multiplier - Disable Lower Bound 2', fileName, '0x76198BC70F57C0F3480F2AC0F30F59C1F3480F2CC08986B00000', '0x76008BC70F57C0F3480F2AC0F30F59C1F3480F2CC08986B00000', 0, 'bool')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customDrachmaeMultiplierDisableLowerBound3 = cByteArrayHack('Custom Drachmae Multiplier - Disable Lower Bound 3', fileName, '0x73740F28CEE89BF0D2FF488B8FE8010000', '0x74740F28CEE8CBCAD0FF488B8FE8010000', 0, 'bool')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customDrachmaeMultiplierDisableLowerBound4 = cByteArrayHack('Custom Drachmae Multiplier - Disable Lower Bound 4', fileName, '0x0F862B02000084C00F85230200004038B7F40100000F847601000048', '0x0F842B02000084C00F85230200004038B7F40100000F847601000048', 0, 'bool')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customXPMultiplier = cByteArrayHack('Custom XP Multiplier', fileName, '0xC333C0C3CC488B81880000004885C0741280B8D1000000007409F30F1080E4000000C3F30F1005AE5E5202C3CC', '0x9033C0C3CC488B81880000004885C0740980B8D1000000007400C780E40000000000C03FF30F1080E4000000C3', 64, 'float')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customXPMultiplierDisableLowerBound1 = cByteArrayHack('Custom XP Multiplier - Disable Lower Bound 1', fileName, '0x0F2F0D3D216B017208F30F118998050000C3', '0x0F2F0D6D2B6B017200F30F118998050000C3', 0, 'bool')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customXPMultiplierDisableLowerBound2 = cByteArrayHack('Custom XP Multiplier - Disable Lower Bound 2', fileName, '0x0F2F0DFD77700176300F57C0F3480F2AC5F30F59C1F3480F2CC00F57C08983B4', '0x0F2F0D0D94680176000F57C0F3480F2AC5F30F59C1F3480F2CC00F57C08983B4', 0, 'bool')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customXPMultiplierDisableLowerBound3 = cByteArrayHack('Custom XP Multiplier - Disable Lower Bound 3', fileName, '0x73740F28CEE890F3D2FF488B8FE8010000', '0x74740F28CEE8C0CDD0FF488B8FE8010000', 0, 'bool')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customXPMultiplierDisableLowerBound4 = cByteArrayHack('Custom XP Multiplier - Disable Lower Bound 4', fileName, '0x0F86FF01000084C00F85F70100004038B7F30100000F844A01000048', '0x0F84FF01000084C00F85F70100004038B7F30100000F844A01000048', 0, 'bool')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customEnemyHealthMultiplier = cByteArrayHack('Custom Enemy Health Multiplier', fileName, '0x74124883C208483BD175EEF30F1005676B9001C34885C074F2F30F104010C3CCCCCCCCCCCCCC', '0x74124883C208483BD175EEF30F1005F7369001C34885C074F2C740100000C03FF30F104010C3', 56, 'float')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customEnemyDamageMultiplier = cByteArrayHack('Custom Enemy Damage Multiplier', fileName, '0x74124883C208483BD175EEF30F1005B76B9001C34885C074F2F30F10400CC3CCCCCCCCCCCCCC', '0x74124883C208483BD175EEF30F100547379001C34885C074F2C7400C0000C03FF30F10400CC3', 56, 'float')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customMaxEnemyLevelDelta = cByteArrayHack('Custom Max Enemy Level Delta', fileName, '0x4883EC28E8C72200004885C074088B40184883C428C3B8040000004883C428C3', '0x4883EC28E8C72200004885C07400B8FF0000004883C428C3CCCCCCCCCCCCCCCC', 30, 'byte')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customHealingReduction1 = cByteArrayHack('Custom Healing - Healing Factor', fileName, '0x488B4F18428D149D00000000F3440F2C040A440FAF453841F7E841B801000000C1FA058BC2C1E81F03D0440F45C2418BC8', '0x4C8B1DCE346D034831C9418B8B080700009090904D31C0498BD1C1FA0A85C97605D1E283C2019090909090909090488BCA', 56, 'byte')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customHealingReduction2 = cByteArrayHack('Custom Healing - Reduced Health Boosts', fileName, '0x8D1431488BCFE8AACB13003BF30F94C084C074304084ED752BE8C77EAC00488BD84885C0741E488D4C2420E835B297FE488D8B200600004533C0488D542420E831CA61FF488B9C247002000033C0488B8C24300200004833CCE8C7E1AF014881C4400200005F5E5DC3CCCCCCCCCCCCCCCCCCCCCCCC', '0xEB6790488BCFE8AACB13003BF30F94C084C074304084ED752BE8C77EAC00488BD84885C0741E488D4C2420E835B297FE488D8B200600004533C0488D542420E831CA61FF488B9C247002000033C0488B8C24300200004833CCE8C7E1AF014881C4400200005F5E5DC3C1FE018D1431EB92CCCCCCCC', 214, 'byte')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customResourceLootModifier = cByteArrayHack('Custom Resource Loot Modifier', fileName, '0xFF50700F57C9B801000000F3480F2ACBF30F59C1F3480F2CC885C90F45C1', '0xFF50700F57C9B801000000F3480F2ACBF30F59C1F3480F2CC048C1E00190', 56, 'byte')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customTamedAnimalHealthBoost1 = cByteArrayHack('Tamed Animal Health Boost Patch 1', fileName, '0x488BCB0F5BC0F30F5980F4010000F3440F2CC0', '0x488BCB0F5BC0F30F5980F4010000E9C9840000', 0, 'bool')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customTamedAnimalHealthBoost2 = cByteArrayHack('Tamed Animal Health Boost Patch 2', fileName, '0xCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC48895C240848896C24104889742418574883EC20488BFA498BE80FB75158488BF1488BCF41B830000000', '0x448B90F4010000C780F40100000000C03FF30F5980F4010000448990F4010000F3440F2CC0E90D7BFFFFCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC48895C240848896C24104889742418574883EC20488BFA498BE80FB75158488BF1488BCF41B830000000', 26, 'float')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customTamedAnimalInCombatHealing = cByteArrayHack('Tamed Animal In Combat Healing', fileName, '0x837E3802660F6EF00F5BF60F84B0000000', '0x837E3802660F6EF00F5BF6740490909090', 0, 'bool')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customTamedAnimalHealingMultiplier1 = cByteArrayHack('Tamed Animal Healing Multiplier Patch 1', fileName, '0xF30F59052780B401F30F5886580100000F28C8F30F118658010000', '0xE99B9A0100909090F30F5886580100000F28C8F30F118658010000', 0, 'bool')
INITIALISED_TWEAKS += 1
print('\x1b[F' + 'Initialising...please be patient...(%.0f%%)' % float(INITIALISED_TWEAKS / NUM_TWEAKS * 100))
customTamedAnimalHealingMultiplier2 = cByteArrayHack('Tamed Animal Healing Multiplier Patch 2', fileName, '0xCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC4883EC28488B491883B92801000000', '0xF30F590587E5B20141BB0000803E66450F6EDBF3410F59C341BB0000803F66450F6EDBF3410F58C3E93B65FEFFCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC4883EC28488B491883B92801000000', 20, 'float')
tweak_collection = {'horseHack':horseHack,
'customDrachmaeMultiplier':customDrachmaeMultiplier,
'customDrachmaeMultiplierDisableLowerBound1':customDrachmaeMultiplierDisableLowerBound1,
'customDrachmaeMultiplierDisableLowerBound2':customDrachmaeMultiplierDisableLowerBound2,
'customDrachmaeMultiplierDisableLowerBound3':customDrachmaeMultiplierDisableLowerBound3,
'customDrachmaeMultiplierDisableLowerBound4':customDrachmaeMultiplierDisableLowerBound4,
'customXPMultiplier':customXPMultiplier,
'customXPMultiplierDisableLowerBound1':customXPMultiplierDisableLowerBound1,
'customXPMultiplierDisableLowerBound2':customXPMultiplierDisableLowerBound2,
'customXPMultiplierDisableLowerBound3':customXPMultiplierDisableLowerBound3,
'customXPMultiplierDisableLowerBound4':customXPMultiplierDisableLowerBound4,
'customEnemyHealthMultiplier':customEnemyHealthMultiplier,
'customEnemyDamageMultiplier':customEnemyDamageMultiplier,
'customMaxEnemyLevelDelta':customMaxEnemyLevelDelta,
'customHealingReduction1':customHealingReduction1,
'customHealingReduction2':customHealingReduction2,
'customResourceLootModifier':customResourceLootModifier,
'customTamedAnimalHealthBoost1':customTamedAnimalHealthBoost1,
'customTamedAnimalHealthBoost2':customTamedAnimalHealthBoost2,
'customTamedAnimalInCombatHealing':customTamedAnimalInCombatHealing,
'customTamedAnimalHealingMultiplier1':customTamedAnimalHealingMultiplier1,
'customTamedAnimalHealingMultiplier2':customTamedAnimalHealingMultiplier2}
return tweak_collection
def NumActiveTweaks(tweak_list):
active_tweaks = 0
for item_name in tweak_list:
item_instance = tweak_list.get(item_name)
if isinstance(item_instance, cByteArrayHack) and item_instance.status == 'Active':
active_tweaks += 1
return active_tweaks
def NumErrorTweaks(tweak_list):
error_tweaks = 0
for item_name in tweak_list:
item_instance = tweak_list.get(item_name)
if isinstance(item_instance, cByteArrayHack) and item_instance.status == 'Error':
error_tweaks += 1
return error_tweaks
def DisplayWelcomeMessage():
print('\x1b[1;32;40mWelcome to AC Odyssey Tweak Pack ' + CURRENT_VERSION + '!' + '\x1b[0m')
print('By Vahndaar')
print('\x1b[1;33;40mCompatible With ' + COMPATIBLE_VERSION + '\x1b[0m')
print('\x1b[1;31;40m***DISCLAIMER! MODIFY THE GAME FILES AT YOUR OWN RISK***\x1b[0m')
print('===============================================================================================================')
def GetExeFile():
print('Seaching for game executable...', end='')
fileName = ''
keys = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, 'Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache')
try:
i = 0
while True:
key_name, key_value, key_type = winreg.EnumValue(keys, i)
if key_name.find("\\Assassin's Creed Odyssey\\ACOdyssey.exe.FriendlyAppName", 0) > 0:
fileName = key_name[0:len(key_name) - 16]
i += 1
except WindowsError:
print('done!')
if fileName != '':
print('ACOdyssey.exe found here : ' + fileName)
print('')
keyed_input = ''
while keyed_input != 'y' and keyed_input != 'Y' and keyed_input != 'n' and keyed_input != 'N':
keyed_input = input('Is this the correct file path?(Y/N): ')
if keyed_input == 'y' or keyed_input == 'Y':
break
if keyed_input == 'n' or keyed_input == 'N':
fileName = ''
break
print('Please respond either Y or N')
else:
print("Couldn't find ACOdyssey.exe.")
if fileName == '':
fileName = input('Please enter the file path for your ACOdyssey.exe file: ')
print('Checking file...')
if is_pathname_valid(fileName) == False:
print('Path is not valid, exiting...')
raise SystemExit('Path is not valid, exiting...')
print('Path is valid.')
if os.path.basename(fileName) != 'ACOdyssey.exe':
print('Incorrect file name, not ACOdyssey.exe, exiting...')
raise SystemExit('Incorrect filename, exiting...')
print('Filename is valid.')
return fileName
def CheckForBackup(fileName: str):
backup_dir = os.path.dirname(os.path.abspath(fileName))
backup_file = backup_dir + os.path.sep + 'ACOdyssey.exe.backup'
if not is_pathname_valid(backup_file):
return False
else:
return True
def SaveBackup(active_tweaks: int, fileName: str):
file_saved = False
if active_tweaks == 0:
keyed_input = ''
while keyed_input != 'y' and keyed_input != 'Y' and keyed_input != 'n' and keyed_input != 'N':
keyed_input = input('Currently no tweaks are active, would you like to backup your file? (Y/N): ')
if keyed_input == 'y' or keyed_input == 'Y':
backup_dir = os.path.dirname(os.path.abspath(fileName))
backup_file = backup_dir + os.path.sep + 'ACOdyssey.exe.backup'
copyfile(fileName, backup_file)
break
if keyed_input == 'n' or keyed_input == 'N':
break
print('Please respond either Y or N')
else:
print('There are tweaks active. Disable them before saving to ensure a clean backup.')
keyed_input = input('Press a key to continue...')
file_saved = CheckForBackup(fileName)
return file_saved
DisplayWelcomeMessage()
fileName = GetExeFile()
tweaks = InitialiseTweaks()
backup_exists = CheckForBackup(fileName)
keyed_input = ''
while keyed_input != 'X' and keyed_input != 'x':
WriteMenu(tweaks, CheckForBackup(fileName))
keyed_input = input('Please select an option: ')
if keyed_input == '1':
tweak = tweaks['horseHack']
if tweak.status == 'Inactive':
tweak.Enable()
continue
if tweak.status == 'Active':
tweak.Disable()
continue
if keyed_input == '2':
tweak = tweaks['customXPMultiplier']
if tweak.status == 'Inactive':
try:
new_value = float(input('Set multiplier value to : '))
if new_value < 0.0:
print('Cannot be less than 0.')
k = input('Press a key to continue...')
continue
temp = BitArray(floatle=new_value, length=32)
temp2 = BitArray(tweak.modifiedByteArray)
temp2.overwrite(temp, tweak.variableOffset * 4)
tweak.modifiedByteArray = '0x' + temp2.hex
tweak.Enable()
if new_value < 1.0:
print('Value < 1.00, disabling lower multiplier limits...')
tweaks['customXPMultiplierDisableLowerBound1'].Enable()
tweaks['customXPMultiplierDisableLowerBound2'].Enable()
tweaks['customXPMultiplierDisableLowerBound3'].Enable()
tweaks['customXPMultiplierDisableLowerBound4'].Enable()
else:
tweaks['customXPMultiplierDisableLowerBound1'].Disable()
tweaks['customXPMultiplierDisableLowerBound2'].Disable()
tweaks['customXPMultiplierDisableLowerBound3'].Disable()
tweaks['customXPMultiplierDisableLowerBound4'].Disable()
continue
except ValueError:
print('Only numerical values accepted!')
k = input('Press a key to continue...')
continue
if tweak.status == 'Active':
tweak.Disable()
tweaks['customXPMultiplierDisableLowerBound1'].Disable()
tweaks['customXPMultiplierDisableLowerBound2'].Disable()
tweaks['customXPMultiplierDisableLowerBound3'].Disable()
tweaks['customXPMultiplierDisableLowerBound4'].Disable()
continue
if keyed_input == '3':
tweak = tweaks['customEnemyHealthMultiplier']
if tweak.status == 'Inactive':
try:
new_value = float(input('Set enemy health multiplier to : '))
if new_value < 0.0:
print('Cannot be less than 0.')
k = input('Press a key to continue...')
continue
temp = BitArray(floatle=new_value, length=32)
temp2 = BitArray(tweak.modifiedByteArray)
temp2.overwrite(temp, tweak.variableOffset * 4)
tweak.modifiedByteArray = '0x' + temp2.hex
tweak.Enable()
continue
except ValueError:
print('Only numerical values accepted!')
k = input('Press a key to continue...')
continue
if tweak.status == 'Active':
tweak.Disable()
continue
if keyed_input == '4':
tweak = tweaks['customEnemyDamageMultiplier']
if tweak.status == 'Inactive':
try:
new_value = float(input('Set enemy damage multiplier to : '))
if new_value < 0.0:
print('Cannot be less than 0.')
k = input('Press a key to continue...')
continue
temp = BitArray(floatle=new_value, length=32)
temp2 = BitArray(tweak.modifiedByteArray)
temp2.overwrite(temp, tweak.variableOffset * 4)
tweak.modifiedByteArray = '0x' + temp2.hex
tweak.Enable()
continue
except ValueError:
print('Only numerical values accepted!')
k = input('Press a key to continue...')
continue
if tweak.status == 'Active':
tweak.Disable()
continue
if keyed_input == '5':
tweak = tweaks['customMaxEnemyLevelDelta']
if tweak.status == 'Inactive':
try:
new_value = int(input('Set max delta to (0-255) : '))
if new_value < 0:
print('Cannot be less than 0.')
k = input('Press a key to continue...')
continue
temp = BitArray(uint=new_value, length=8)
temp2 = BitArray(tweak.modifiedByteArray)
temp2.overwrite(temp, tweak.variableOffset * 4)
tweak.modifiedByteArray = '0x' + temp2.hex
tweak.Enable()
continue
except ValueError:
print('Only whole numbers in the range 0 - 255 accepted!')
k = input('Press a key to continue...')
continue
if tweak.status == 'Active':
tweak.Disable()
continue
if keyed_input == '6':
tweak = tweaks['customDrachmaeMultiplier']
if tweak.status == 'Inactive':
try:
new_value = float(input('Set multiplier value to : '))
if new_value < 0.0:
print('Cannot be less than 0.')
k = input('Press a key to continue...')
continue
if new_value < 0.5:
print('Setting less than 0.5 may result in some loot awarding no drachmae.')
temp = BitArray(floatle=new_value, length=32)
temp2 = BitArray(tweak.modifiedByteArray)
temp2.overwrite(temp, tweak.variableOffset * 4)
tweak.modifiedByteArray = '0x' + temp2.hex
tweak.Enable()
if new_value < 1.0:
print('Value < 1.00, disabling lower multiplier limits...')
tweaks['customDrachmaeMultiplierDisableLowerBound1'].Enable()
tweaks['customDrachmaeMultiplierDisableLowerBound2'].Enable()
tweaks['customDrachmaeMultiplierDisableLowerBound3'].Enable()
tweaks['customDrachmaeMultiplierDisableLowerBound4'].Enable()
else:
tweaks['customDrachmaeMultiplierDisableLowerBound1'].Disable()
tweaks['customDrachmaeMultiplierDisableLowerBound2'].Disable()
tweaks['customDrachmaeMultiplierDisableLowerBound3'].Disable()
tweaks['customDrachmaeMultiplierDisableLowerBound4'].Disable()
continue
except ValueError:
print('Only numerical values accepted!')
k = input('Press a key to continue...')
continue
if tweak.status == 'Active':
tweak.Disable()
tweaks['customDrachmaeMultiplierDisableLowerBound1'].Disable()
tweaks['customDrachmaeMultiplierDisableLowerBound2'].Disable()
tweaks['customDrachmaeMultiplierDisableLowerBound3'].Disable()
tweaks['customDrachmaeMultiplierDisableLowerBound4'].Disable()
continue
if keyed_input == '7':
tweak = tweaks['customHealingReduction1']
if tweak.status == 'Inactive':
try:
new_value = int(input('Set healing factor (1-15): '))
if new_value < 1 or new_value > 15:
print('Only whole numbers in the range 1 - 15 accepted!')
k = input('Press a key to continue...')
continue
temp = BitArray(uint=new_value, length=8)
temp2 = BitArray(tweak.modifiedByteArray)
temp2.overwrite(temp, tweak.variableOffset * 4)
tweak.modifiedByteArray = '0x' + temp2.hex
tweak.Enable()
continue
except ValueError:
print('Only whole numbers in the range 1 - 15 accepted!')
k = input('Press a key to continue...')
continue
if tweak.status == 'Active':
tweak.Disable()
continue
if keyed_input == '8':
tweak = tweaks['customHealingReduction2']
if tweak.status == 'Inactive':
try:
new_value = int(input('Set health boost reduction factor to (1-5) : '))
if new_value < 1 or new_value > 5:
print('Only whole numbers in the range 1 - 5 accepted!')
k = input('Press a key to continue...')
continue
temp = BitArray(uint=new_value, length=8)
temp2 = BitArray(tweak.modifiedByteArray)
temp2.overwrite(temp, tweak.variableOffset * 4)
tweak.modifiedByteArray = '0x' + temp2.hex
tweak.Enable()
continue
except ValueError:
print('Only whole numbers in the range 1 - 5 accepted!')
k = input('Press a key to continue...')
continue
if tweak.status == 'Active':
tweak.Disable()
continue
if keyed_input == '9':
tweak = tweaks['customResourceLootModifier']
if tweak.status == 'Inactive':
try:
new_value = int(input('Set resource loot multiplication factor to (1-5) : '))
if new_value < 1 or new_value > 5:
print('Only whole numbers in the range 1 - 5 accepted!')
k = input('Press a key to continue...')
continue
temp = BitArray(uint=new_value, length=8)
temp2 = BitArray(tweak.modifiedByteArray)
temp2.overwrite(temp, tweak.variableOffset * 4)
tweak.modifiedByteArray = '0x' + temp2.hex
tweak.Enable()
continue
except ValueError:
print('Only whole numbers in the range 1 - 5 accepted!')
k = input('Press a key to continue...')
continue
if tweak.status == 'Active':
tweak.Disable()
continue
if keyed_input == '10':
tweak = tweaks['customTamedAnimalHealthBoost2']
if tweak.status == 'Inactive':
try:
new_value = float(input('Set animal companion health multiplier to : '))
if new_value < 1.0:
print('Cannot be less than 1.')
k = input('Press a key to continue...')
continue
temp = BitArray(floatle=new_value, length=32)
temp2 = BitArray(tweak.modifiedByteArray)
temp2.overwrite(temp, tweak.variableOffset * 4)
tweak.modifiedByteArray = '0x' + temp2.hex
tweaks['customTamedAnimalHealthBoost1'].Enable()
tweak.Enable()
continue
except ValueError:
print('Only numerical values accepted!')
k = input('Press a key to continue...')
continue
if tweak.status == 'Active':
tweaks['customTamedAnimalHealthBoost1'].Disable()
tweak.Disable()
continue
if keyed_input == '11':
tweak = tweaks['customTamedAnimalInCombatHealing']
if tweak.status == 'Inactive':
tweak.Enable()
elif tweak.status == 'Active':
tweak.Disable()
continue
if keyed_input == '12':
tweak = tweaks['customTamedAnimalHealingMultiplier2']
if tweak.status == 'Inactive':
try:
new_value = float(input('Set animal companion healing multiplier to : '))
if new_value < 0.0:
print('Cannot be less than 0.')
k = input('Press a key to continue...')
continue
temp = BitArray(floatle=new_value, length=32)
temp2 = BitArray(tweak.modifiedByteArray)
temp2.overwrite(temp, tweak.variableOffset * 4)
tweak.modifiedByteArray = '0x' + temp2.hex
tweaks['customTamedAnimalHealingMultiplier1'].Enable()
tweak.Enable()
continue
except ValueError:
print('Only numerical values accepted!')
k = input('Press a key to continue...')
continue
if tweak.status == 'Active':
tweaks['customTamedAnimalHealingMultiplier1'].Disable()
tweak.Disable()
continue
if keyed_input == 'R' or keyed_input == 'r':
os.startfile(fileName)
if keyed_input == 'L' or keyed_input == 'l':
if CheckForBackup(fileName) == True:
backup_dir = os.path.dirname(os.path.abspath(fileName))
backup_file = backup_dir + os.path.sep + 'ACOdyssey.exe.backup'
print('Restoring backup file...')
try:
copyfile(backup_file, fileName)
except IOError:
print("Unable to restore backup. Ensure the file isn't in use and try again.")
k = input('Press a key to continue...')
continue
tweaks = InitialiseTweaks()
if keyed_input == 'D' or keyed_input == 'd':
if NumActiveTweaks(tweaks) > 0:
for tweak_name in tweaks:
tweak = tweaks.get(tweak_name)
if isinstance(tweak, cByteArrayHack) and tweak.status == 'Active':
tweak.Disable()
if keyed_input == 'S' or keyed_input == 's':
if NumActiveTweaks(tweaks) == 0:
SaveBackup(0, fileName)
if keyed_input == 'X' or keyed_input == 'x':
k = input('Thanks for using this tool! Enjoy! VD')
# okay decompiling ACOdyssey Tweak Pack V0.8 (V1.1.4)-12-V0-8-1551308095.exe_extracted\ACOdyssey Tweak Pack_with_pymagic.pyc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment