-
-
Save Andoryuuta/f4772f831fffb073a8a13d6c4e026da0 to your computer and use it in GitHub Desktop.
ACOdyssey Tweak Pack V0.8 (V1.1.4) decompiled
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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