def randomizeWorldRoutes():
    if shouldIRandomize:
        file = "00progress.bin"
        if (copyKHFile(file)):
            fileBin = open(file, "rb+")
            writeRandomizationLog(file)
            if (fileBin):
                findHeaderinBAR(fileBin, 'wldf', True)
                fileBin.seek(0x4, 1)  #skip a number
def openKHText(file):  #ex : file:msg/jp/tt.bar
    #open file, grab all strings, then when we finish modifying all the strings, get the length of them all and replace.
    #Unordered list with ID and Position.
    fileBin = open(file, 'rb+')
    offset = findBarHeader(fileBin)
    test = (
        file[len(file) - 4 - 2:]
    )[:
      2]  #Find world name by removing the last 4 characters and subtracting the length to start at the world name
    findHeaderinBAR(fileBin, test, False)
    fileBin.seek(0x8, 1)  # skip header thing
    stringSize = readAndUnpack(fileBin, 4)
    findHeaderinBAR(fileBin, test, True)
    startingStringTablePos = fileBin.tell()
    fileBin.seek(0x4, 1)  #skip header thing
    amountOfTextLines = readAndUnpack(fileBin, 4)
    stringList = []
    for x in range(amountOfTextLines):

        fileBin.seek(startingStringTablePos + 8 + (x * 8), 0)
        stringID = readAndUnpack(fileBin, 4)
        stringPos = readAndUnpack(fileBin, 4)
        filterStuff = list(
            filter(lambda x: (stringPos == x.position), stringList))
        if len(filterStuff) != 0:
            filterStuff[0].addID(stringID)
        else:
            stringList.append(TextBar(stringID, stringPos, ''))

    stringList = sorted(stringList, key=lambda x: x.position)
    fileBin.seek(startingStringTablePos + 8 + (amountOfTextLines * 8), 0)
    for x in range(len(stringList)):
        stringData = []
        currentChar = -1
        currentNextID = 1

        if x < len(stringList) - 1:
            lengthOfString = (stringList[x + currentNextID].position -
                              stringList[x].position)
            while lengthOfString > 0:
                currentChar = readAndUnpack(fileBin, 1)
                stringData.append(currentChar)
                lengthOfString -= 1
        else:
            lengthOfString = ((stringSize) - stringList[x].position)
            while lengthOfString > 0:
                currentChar = readAndUnpack(fileBin, 1)
                stringData.append(currentChar)
                lengthOfString -= 1

        stringList[x].text = stringData
    fileBin.close()
    return stringList
def closeKHText(file, strings):

    fileBin = open(file, 'rb+')
    offset = findBarHeader(fileBin)
    findHeaderinBAR(fileBin, 'md_m', False)
    fileBin.seek(0x8, 1)
    md_m_size = readAndUnpack(fileBin, 4)
    findHeaderinBAR(fileBin, 'md_m', True)
    md_m_Data = fileBin.read(md_m_size)
    miscData = fileBin.read()
    test = (
        file[len(file) - 4 - 2:]
    )[:
      2]  # Find world name by removing the last 4 characters and subtracting the length to start at the world name
    findHeaderinBAR(fileBin, test, True)
    startingStringTablePos = fileBin.tell()
    fileBin.seek(0x4, 1)  # skip header thing
    amountOfTextLines = readAndUnpack(fileBin, 4)
    startReadingPos = fileBin.tell()
    fileBin.seek(startingStringTablePos + 8 + (amountOfTextLines * 8), 0)
    for x in strings:
        x.position = fileBin.tell() - startingStringTablePos
        newList = x.writeBackToFile()
        for character in newList:
            writeIntOrHex(fileBin, character, 1)

    fileEndSize = fileBin.tell() - offset
    fileBin.truncate(fileEndSize)
    newTextBarFileSize = fileEndSize - startingStringTablePos
    while fileBin.tell() % 16 != 0:
        writeIntOrHex(fileBin, 0, 1)
    newMd_mPos = fileBin.tell() - offset

    fileBin.write(md_m_Data)
    ModifyExtraFilePosition(
        fileBin,
        fileBin.tell())  #we want relative positions to 0,0 of the file.
    fileBin.write(miscData)
    fileBin.seek(startReadingPos,
                 0)  #Go back to the start with ids and positions
    for x in strings:
        stringID = readAndUnpack(fileBin, 4)
        filterStuff = list(filter(lambda x: (stringID in x.ids), strings))
        writeIntOrHex(fileBin, filterStuff[0].position,
                      4)  #Write new positions of text
    findHeaderinBAR(fileBin, 'md_m', False)
    fileBin.seek(0x4, 1)
    writeIntOrHex(fileBin, newMd_mPos, 4)
    findHeaderinBAR(fileBin, test, False)
    fileBin.seek(0x8, 1)
    writeIntOrHex(fileBin, newTextBarFileSize, 4)
    fileBin.close()
Example #4
0
def skipGummiShipMissions(doItOrNot):
    #set roxas and kh1 sora to kh2 sora
    if doItOrNot:
        print("Skipping gummiship missions...")
        if copyKHFile("00progress.bin"):
            fileBin = open("00progress.bin", 'rb+')
            if (fileBin):
                skipCode = [
                    0x04, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0A, 0x00,
                    0x01, 0x00, 0x01, 0x00, 0x00
                ]
                findHeaderinBAR(fileBin, 'wldf', True)
                if PS3Version():
                    skipCode.insert(0, 0x00)
                fileBin.seek(0x9b4, 1)
                fileBin.write(bytearray(skipCode))
                print("Done!")
                fileBin.close()
Example #5
0
def RandomizeCriticalBonusAbilities(shouldIrandomize, shouldIrandomize2):
    offSetSeed(5)
    if (shouldIrandomize and shouldIrandomize2):
        print("Modifying critical bonus abilities...")
        if (copyKHFile("00battle.bin")):
            fileBin = open("00battle.bin", 'rb+')
            findHeaderinBAR(
                fileBin, 'plrp',
                True)  # skip to nearest bar closest to where we want to go
            if (fileBin):
                fileBin.seek(0x1f94, 1)  #skip to critical mode abilities
                currentPos = fileBin.tell()
                critBonusNum = 300
                for i in range(7):
                    fileBin.seek(currentPos + (i * 2), 0)
                    OldAbility = readAndUnpack(fileBin, 2)
                    fileBin.seek(-2, 1)  # Go bak
                    if OldAbility != 0x194:  #Do not randomize no exp
                        newList = list(
                            filter(lambda d: d.character == KHCharacter.Sora,
                                   AbilityList[AbilityTable_enum.Support])
                        )  # Check for same character
                        newList = list(
                            filter(
                                lambda d: d.abilityLearned == AbilityTypeGained
                                .CriticalBonus, newList))
                        newList = list(filter(lambda d: d.emptyItem(),
                                              newList))
                        if len(newList) != 0:
                            random.shuffle(newList)
                            fromNewList = AbilityList[
                                AbilityTable_enum.Support].index(newList[0])
                            AbilityList[AbilityTable_enum.
                                        Support][fromNewList].subtractQOne()
                            writeIntOrHex(
                                fileBin, AbilityList[AbilityTable_enum.Support]
                                [fromNewList].code, 2)
                            writeOutCome_BonusLevel(
                                KHCharacter.Sora, critBonusNum,
                                AbilityList[AbilityTable_enum.Support]
                                [fromNewList].name)
                            critBonusNum += 1
Example #6
0
 def shopItemChanging():
     findHeaderinBAR(fileBin, 'shop', True)
     itemsToChange = int(
         0x3a0 /
         2)  #Size divided by entry size to get total entries
     fileBin.seek(
         0xC70, 1
     )  #skip all this data i dont know about and go to items
     for shop_item in range(itemsToChange):
         CurrentList = list(
             filter(lambda x: (x.emptyItem()), ItemList_Shop))
         previousItem = readAndUnpack(fileBin, 2)
         fileBin.seek(-2, 1)
         chooseShopItem = random.choice(CurrentList)
         ItemList_Shop[ItemList_Shop.index(
             chooseShopItem)].subtractQOne()
         writeIntOrHex(fileBin, chooseShopItem.codeReturn(), 2)
         writeOutCome_ItemShop(
             shop_item, "OLD: " + "{:<20}".format(
                 findItemInList(ItemList_Shop,
                                previousItem).name) + "NEW:" +
             "{:<20}".format(chooseShopItem.name))
Example #7
0
def giveHUDElements():
    pass  #Don't do this for now, it sets all battle levels of worlds to lvl 1 which makes things too easy.
    """ progressBin data
    bar file inside bar file == so it has its own header with positions and such 
    0C ?? ?? ?? == Plays or starts a event of some kind? Always starts with 0C. May have something like a prefix
    0C 01 91 08 -- Start playing as KH1 Sora
    01 == Event Type? 01 or 02 and sometimes 0?
    91 == Event ID
    
    These event Id's dont show up anywhere else i can find ATM so i have no idea on how to manipluate these into not removing the hud elements
    These events when triggered also seem to affect the save data part of RAM 
    """
    print("Giving hud elements early...")
    if copyKHFile("00progress.bin"):
        fileBin = open("00progress.bin", 'rb+')
        if (fileBin):
            hudCode = [0x00]
            findHeaderinBAR(fileBin, 'tt', True)
            fileBin.seek(0x6fa, 1)
            fileBin.write(bytearray(hudCode))
            fileBin.close()
            print("Done!")
Example #8
0
 def itemShopBuyingSellingPrices():
     findHeaderinBAR(fileBin, 'item', True)
     fileBin.seek(0x4, 1)
     itemsToChange = readAndUnpack(fileBin, 4)
     OrgPos = fileBin.tell()
     for item in range(itemsToChange):
         fileBin.seek(OrgPos + (item * 0x18), 0)
         itemID = readUnpackGoBack(fileBin, 2)
         fileBin.seek(0xC, 1)
         BuyPriceExisting = readUnpackGoBack(fileBin, 2)
         #loop through and find item in list
         newItem = -1
         for item_x in ItemList_Shop:
             if item_x.codeReturn() == itemID:
                 newItem = item_x
                 break
         if newItem != -1 and item_x.shopPrice != -1:
             writeIntOrHex(fileBin, item_x.shopPrice,
                           2)  #Write new shop buy money
             writeIntOrHex(
                 fileBin, int(item_x.shopPrice * 0.50), 2
             )  #Write new shop sell money times 0.50 of buy price
    def FixMulanMSNSoftlock():
        findHeaderinBAR(fileBin, 'btl', True)
        stringToFind = ReverseEndianString('MU02_MS103B', 2, True,True).encode()
        posBefore = fileBin.tell()
        readData = fileBin.read()
        newPos = readData.find(stringToFind)
        fileBin.seek(posBefore + newPos, 0)
        #MSNFile text ID location : 0x14 from the first position == textid
        #MSNFile Help/Continue Pause button toggler: 0x16 from first position and needs to be 0x18 to work
        """
        What mission file seems to determine:
        First Mission Bar Entry:
        If enemies should drop items
        How pausing should work
        What text ID to display on the information tab
        
        Second Mission Bar Entry:
        ???
        Probably controls when enemies should attack during the camera movement phase
        Anything Else after these two entries:
        Camera Movement & Panning at the start of the mission
        Camera Movement & Panning when a boss dies or something fails
        The graphical effect when you defeat a boss
        ^ intrestingly unique for many fights. Take a look at Lingering Will's defeat camera and effect VS when roxas is defeated
        What images should be displayed EX: Luxord time bar, Mulan's Heartless Count and Motivation bar
        
        Seems like how enemies should spawn in is determined by ARD files not by MSN files
        
        MSN Files are loaded through reference in the ard file from 'BTL' and usually is assigned to an entry starting with 'b_'
"""
        newMSNFile_Location = msnFileCreate_NonBoss('MU02_MS103A')
        fileBin.write(ReverseEndianString('MU02_MS103A_R', 2, True, True).encode())
        MsnFileBin = open(newMSNFile_Location, 'rb+')
        findHeaderinBAR(MsnFileBin, 'MU02', True)
        MsnFileBin.seek(0x38, 1)
        writeIntOrHex(MsnFileBin, 0x0C, 4)
        MsnFileBin.close()
Example #10
0
def ReduceFormGrinding(shouldIreduce):
    if (shouldIreduce):
        print("Reducing form grinding...")
        if (copyKHFile("00battle.bin")):
            fileBin = open("00battle.bin", 'rb+')  # skip 4 bytes
            findHeaderinBAR(fileBin, 'fmlv', True)  # skip 4 bytes
            if (fileBin):
                fileBin.seek(0x8, 1)  #skip foward 8
                for formType in range(5):
                    for formLevel in range(6):
                        levelUpsStartPos = fileBin.tell(
                        )  # gimmie our currentPosition
                        fileBin.seek(0x1,
                                     1)  # skip level byte, we know it already
                        FormLVL = readAndUnpack(fileBin, 1)
                        AbilityFormLvlUp = readAndUnpack(fileBin, 2)
                        FormLVLUpXP = readAndUnpack(fileBin, 4)
                        #times 0.40 drive xp
                        FormLVLUpXP = math.floor(FormLVLUpXP * 0.37)
                        fileBin.seek(-4, 1)
                        writeIntOrHex(fileBin, FormLVLUpXP, 4)
                    fileBin.seek(0x8, 1)

            fileBin.close()
Example #11
0
def RandomizeDriveFormAbilities(shouldIrandomize):
    offSetSeed(4)
    if (shouldIrandomize):
        print("Modifying drive form abilities...")
        if (copyKHFile("00battle.bin")):
            fileBin = open("00battle.bin", 'rb+')  # skip 4 bytes
            findHeaderinBAR(fileBin, 'fmlv', True)  # skip 4 bytes
            if (fileBin):
                fileBin.seek(0x8, 1)  #skip foward 8
                formData = []
                filePos = fileBin.tell()
                #Read
                for formType in FormTypeEnum:
                    formData.append([])
                    for formLevel in range(7):
                        formData[formType].append([])
                        fileBin.seek(0x2,
                                     1)  # skip level byte, we know it already
                        AbilityFormLvlUp = readAndUnpack(fileBin, 2)
                        fileBin.seek(0x4, 1)
                        formData[formType][formLevel] = AbilityFormLvlUp
                #Modify
                formBonusNum = 200
                AutoAbility = {0x181, 0x183, 0x184}
                randomFormType = list(FormTypeEnum)
                random.shuffle(randomFormType)
                randomFormData = list(range(len(formData[formType])))
                random.shuffle(randomFormData)

                for formType in randomFormType:
                    for dt in randomFormData:
                        newList = list(
                            filter(lambda d: d.character == KHCharacter.Sora,
                                   AbilityList[AbilityTable_enum.Support])
                        )  # Check for same character
                        newList = list(
                            filter(
                                lambda d: d.abilityLearned == AbilityTypeGained
                                .DriveForm, newList))
                        newList = list(
                            filter(lambda d: d.emptyItem(),
                                   newList))  # Check if empty ability
                        random.shuffle(newList)
                        if formType in range(1, 6):
                            if formData[formType][dt] != 0:
                                name = ""
                                if formData[formType][dt] == 0x181:
                                    name = 'Auto Valor'
                                if formData[formType][dt] == 0x183:
                                    name = 'Auto Master'
                                if formData[formType][dt] == 0x184:
                                    name = 'Auto Final'
                                if formData[formType][dt] not in AutoAbility:
                                    if len(newList) != 0:
                                        fromNewList = AbilityList[
                                            AbilityTable_enum.Support].index(
                                                newList[0])
                                        AbilityList[AbilityTable_enum.Support][
                                            fromNewList].subtractQOne()
                                        formData[formType][dt] = AbilityList[
                                            AbilityTable_enum.
                                            Support][fromNewList].code
                                        name = AbilityList[
                                            AbilityTable_enum.
                                            Support][fromNewList].name
                                    else:
                                        name = 'None.'
                                        formData[formType][dt] = 0

                                writeOutCome_BonusLevel(
                                    KHCharacter.Sora, formBonusNum,
                                    str(formType.name) + ":" + name)
                        formBonusNum += 1

                #Write
                fileBin.seek(filePos, 0)
                for formType in FormTypeEnum:
                    formData.append([])
                    for formLevel in range(7):
                        formData[formType].append([])
                        fileBin.seek(0x2,
                                     1)  # skip level byte, we know it already
                        AbilityFormLvlUp = writeIntOrHex(
                            fileBin, formData[formType][formLevel], 2)
                        fileBin.seek(0x4, 1)

            fileBin.close()
def RandomizeChestContents(randomizeChests):
    offSetSeed(0)
    if (randomizeChests):
        print("Randomizing chests...")
        if (copyKHFile("03system.bin")):
            fileBin = open("03system.bin", "rb+")
            if (fileBin):
                TreasureFilePosition = 0
                TreasureFileSize = 0
                """So the way this works is that there is a value of hex inside 03system.bin that
                    has the fileposition of the treasure. we navigate to it and get the number of chests in the position in decimal.
                    hex editor displays hex backwards for some odd reason and makes reading pure hex annoying
                    
                    
                    more info:doing file.read(2) in binary files such as done below will be the equivalent of reading 0000
                    reading 1 for 00

                    """
                findHeaderinBAR(fileBin, 'trsr', True)
                TreasureFilePosition = fileBin.tell()
                noChests = 0
                UniqueChestID = 0  #We're going to make our own unique chest id cause I don't trust KH2 at all.
                fileBin.seek(2, 1)  #TrsrMagic
                noChests = readAndUnpack(fileBin, 2)  #noChests
                itemDict = Vividict()
                # because im dumb lets make a dictonary with unique chest item ids
                for i in range(noChests + 1):
                    fileBin.seek(TreasureFilePosition + 4 + 2 + (i * 0xC), 0)
                    Item = readAndUnpack(
                        fileBin,
                        2)  #Item ID that the chest currently contains.
                    Type = readHex(
                        fileBin,
                        1)  #Type of item it is. 0 for chest, 1 for Event.
                    WorldID = readHex(
                        fileBin, 1
                    )  #Which world is it? we can get that chest info here.
                    RoomIndex = readHex(
                        fileBin,
                        1)  #Which room is it? we can get that chest info here.
                    RoomChestIndex = readHex(
                        fileBin, 1
                    )  #Which roomchestindex is it? we can get that chest info here.
                    EventID = readHex(fileBin, 2)
                    itemDict[WorldID][RoomIndex][RoomChestIndex][Type][
                        EventID][Item] = UniqueChestID
                    UniqueChestID += 1
                #because im dumb lets make a dictonary with unique chest item ids

                randomChestLoop = list(range(noChests + 1))
                random.shuffle(
                    randomChestLoop
                )  #We will randomize the order we go through chests in in order to be a bit more random. Kinda odd but yea so we evenly spread out priority items instead of like in a row.
                for i in randomChestLoop:
                    Item = 0
                    Type = 0
                    fileBin.seek(TreasureFilePosition + 4 + 2 + (i * 0xC), 0)
                    Item = readAndUnpack(
                        fileBin,
                        2)  #Item ID that the chest currently contains.
                    Type = readHex(
                        fileBin,
                        1)  #Type of item it is. 0 for chest, 1 for Event.
                    WorldID = readHex(
                        fileBin, 1
                    )  #Which world is it? we can get that chest info here.
                    RoomIndex = readHex(
                        fileBin,
                        1)  #Which room is it? we can get that chest info here.
                    RoomChestIndex = readHex(
                        fileBin, 1
                    )  #Which roomchestindex is it? we can get that chest info here.
                    EventID = readHex(fileBin, 2)
                    UniqueChestID = itemDict[WorldID][RoomIndex][
                        RoomChestIndex][Type][EventID][Item]
                    fileBin.seek(
                        TreasureFilePosition + 4 + 2 + (i * 0xC),
                        0)  #reset back to original position for writing
                    """So now that we've gotten some info about the original item, we can do some randomization stuff
                    We can randomize a certain group of items depending on where the chest location is now that we have the world and room id of those locations."""
                    if (checkIfItemExists(ItemList, Item)
                            and not CheckIfChestBlackListed(
                                WorldID, RoomIndex, UniqueChestID)):
                        newChestVal = randomizeAChest(Item, Type, WorldID,
                                                      RoomIndex, UniqueChestID,
                                                      EventID)
                        writeIntOrHex(fileBin, newChestVal, 2)

                        newitem = findItemInList(ItemList, newChestVal)
                        if isinstance(newitem, kh2rando_item.KHItem):
                            newItemName = newitem.name
                        else:
                            newItemName = "NoItemFound"

                        newitem = findItemInList(ItemList, Item)
                        if isinstance(newitem, kh2rando_item.KHItem):
                            oldItemName = newitem.name
                        else:
                            oldItemName = "NoItemFound"
                        writeOutCome_Chest(WorldID, RoomIndex, Type,
                                           UniqueChestID, oldItemName,
                                           newItemName)

                fileBin.close()
            else:
                ErrorWindow(
                    "The file 03system.bin could not be opened. It's probably in use by another program or instance of this program."
                )

            writeRandomizationLog("03system.bin")
        else:
            ErrorWindow(
                "03system.bin does not exist in the export/KH2/ folder. Make sure nothing has gone wrong during the extraction."
            )
def msnFileCreate(
    fileName, curWorld, curRoom, oldMsnFileName
):  #pass in a mission file name, and the current room and world & will return the new Filename
    #lets check if the filename is equal to currentworld or currentroom
    #Lets also check if a mission file ID (last 3 digits) is already present in a room, otherwise we will overwrite something we wouldnt want to and have the player softlock
    fileExtension = '.bar'
    oldMsnFileName = oldMsnFileName.rstrip(' \t\r\n\0')
    if (fileName[:4] == curWorld.upper() + curRoom.upper()):
        return fileName  #We dont need to do anything in this case.
    searchHeader = oldMsnFileName[:4]
    newFileName = curWorld.upper() + curRoom.upper() + fileName[
        4:] + '_R'  #Add _R so we dont overwrite missions (_R == Randomized)
    importFolderName = "export/KH2/msn/jp/"
    if PS3Version():
        importFolderName = "export/msn/us/"
    exportFolderName = "msn/jp/"
    if PS3Version():
        exportFolderName = "msn/us/"
    if (os.path.isfile(importFolderName + fileName + fileExtension)):
        if not os.path.exists(exportFolderName):
            os.makedirs(exportFolderName)
        try:
            fileBin = open(
                importFolderName + oldMsnFileName.rstrip() + fileExtension,
                'rb+')
        except FileNotFoundError:
            fileBin = open(exportFolderName + oldMsnFileName + fileExtension,
                           'rb+')
        barOffset = findBarHeader(fileBin)
        fileBin.seek(barOffset + 0x18, 0)  #Skip to first header and get pos
        newPos = readAndUnpack(fileBin, 4)
        fileBin.seek(barOffset + newPos, 0)
        fileBin.seek(0xD, 1)
        oldBonusLevel = readAndUnpack(fileBin, 1)
        fileBin.close()
        shutil.copyfile(importFolderName + fileName + fileExtension,
                        exportFolderName + newFileName + fileExtension)
        print("Copying file...")
        writeRandomizationLog(exportFolderName + newFileName + fileExtension)

        fileBin = open(exportFolderName + newFileName + fileExtension,
                       'rb+')  #Modify file to use correct bonus level.
        ModifyExtraFileNames(fileBin, fileName, newFileName)
        #replaceAllStringInFile(fileBin,fileName.lower(),newFileName.lower())
        findHeaderinBAR(fileBin, fileName[:4], True)
        fileBin.seek(0xD, 1)
        writeIntOrHex(fileBin, oldBonusLevel, 1)
        fileBin.close()
        if PS3Version():
            for x in regionFolders:
                filestring = 'msn/' + x + "/" + newFileName + fileExtension
                if not os.path.exists('msn/' + x + '/'):
                    os.makedirs('msn/' + x + '/')
                shutil.copyfile(exportFolderName + newFileName + fileExtension,
                                filestring)
                print("Copying file for another region...")
                writeRandomizationLog(filestring)

        return newFileName
    else:
        print("Couldn't find msn file to copy...")
        return fileName
Example #14
0
def randomizeItemDrops(randomItemD, randomItemDP):
    offSetSeed(7)
    if (randomItemD or randomItemDP):
        print("Randomizing item drops from enemies...")
        if (copyKHFile("00battle.bin")):
            fileBin = open("00battle.bin", "rb+")
            if (fileBin):
                findHeaderinBAR(fileBin, 'przt', True)
                fileBin.seek(4, 1)

                #Size 0x18
                entryAmt = readAndUnpack(fileBin, 4)
                entryPos = fileBin.tell()
                for x in range(entryAmt):
                    fileBin.seek(entryPos + (x * 0x18), 0)
                    entryIndex = readAndUnpack(fileBin, 2)
                    droppedItemList = [0, 0, 0]
                    droppedItemListProbability = [0, 0, 0]
                    fileBin.seek(0xA, 1)
                    writingPosition = fileBin.tell()
                    for i in range(3):  #Clear it
                        writeIntOrHex(fileBin, 0, 2)
                        writeIntOrHex(fileBin, 0, 2)
                    #probability == percentage in clear num == 12% == 12 not 0.12 or anything silly
                    #Randomize items
                    if randomItemD:
                        for itemnum in range(len(droppedItemList)):
                            droppedItemList[itemnum] = random.choice(
                                itemDropList).code
                    if randomItemDP:
                        for itemnum in range(len(droppedItemListProbability)):
                            chanceList = [
                                random.randint(5, 100),
                                random.randint(5, 50),
                                random.randint(5, 25)
                            ]
                            chanceList_Weight = [0.3, 0.5, 0.2]
                            newRando = random.choices(
                                chanceList, k=1, weights=chanceList_Weight)[0]
                            droppedItemListProbability[
                                itemnum] = newRando  # 5% to 100 chance of an item dropping

                    #Write items
                    chanceList = [0, 1, 2, 3]
                    randomItemAmount = random.choices(
                        chanceList, k=1, weights=[0.7, 0.3, 0.2, 0.1])[0]
                    """
                    fileBin.seek(entryPos + (x * 0x18), 0)
                    fileBin.seek(2,1)
                    orbSelectionList = []
                    orbListTypes = range(10)
                    for p in range(random.randint(0,3)): #Select types of the enemy will drop
                        orbSelectionList.append(random.choice(orbListTypes)) #Select which orb type to use
                    for e in range(0xA):
                        if e in orbSelectionList:
                            writeIntOrHex(fileBin,random.randint(0,5),1)#Write amount of orbs to drop
                        else:
                            fileBin.seek(1, 1)
"""
                    fileBin.seek(writingPosition, 0)
                    for newRandomItems in range(randomItemAmount):
                        writeIntOrHex(fileBin, droppedItemList[newRandomItems],
                                      2)
                        writeIntOrHex(
                            fileBin,
                            droppedItemListProbability[newRandomItems], 2)
            fileBin.close()
Example #15
0
def RandomizeLevelUps(shouldIrandomize):
    offSetSeed(6)
    if (shouldIrandomize):
        print("Modifying level ups for all characters...")
        if (copyKHFile("00battle.bin")):
            fileBin = open(
                "00battle.bin",
                'rb+')  # skip like 4 hexs because it has useless data lol
            findHeaderinBAR(fileBin, 'lvup', True)
            if (fileBin):
                levelUpsStartPos = fileBin.tell()  #gimmie our currentPosition
                fileBin.seek(0x40, 1)
                amtOfLevels = readAndUnpack(fileBin, 4)
                #choose some abilities for some choices
                LVLLength = len(AbilityList[AbilityTable_enum.LevelUp])
                lvlAbilitiesList = [[], [], []]
                for lvlupability in AbilityList[AbilityTable_enum.LevelUp]:
                    lvlAbilitiesList[0].append(
                        (lvlupability.code, lvlupability.name))  #Sword
                    lvlAbilitiesList[1].append(
                        (lvlupability.code, lvlupability.name))  #Shield
                    lvlAbilitiesList[2].append(
                        (lvlupability.code, lvlupability.name))  #Staff
                #now shuffle
                random.shuffle(lvlAbilitiesList[0])
                random.shuffle(lvlAbilitiesList[1])
                random.shuffle(lvlAbilitiesList[2])
                noneString = ''
                emptyTuple = (0, noneString)
                AbilityLevelsNums = random.choices(
                    range(1, amtOfLevels), k=LVLLength
                )  #I'd love to do indiviudal levels based on sword,shield  & staff but that would mean weaker lvls
                for chars in range(13):
                    stats = [
                        random.randint(0, 5),
                        random.randint(0, 5),
                        random.randint(0, 5),
                        random.randint(0, 5)
                    ]
                    if (chars == 0):  #sora
                        stats = [2, 6, 2, 0]
                    if (chars == 1):  #donald
                        stats = [1, 5, 2, 5]
                    if (chars == 2):  #goofy
                        stats = [5, 0, 2, 4]
                    SwordAbility_Modified = emptyTuple
                    ShieldAbility_Modified = emptyTuple
                    StaffAbility_Modified = emptyTuple
                    for i in range(amtOfLevels):
                        beforeMoving = fileBin.tell()
                        CurrentLevel = i + 1
                        writeOutCome_LevelUps(
                            chars, i, " STR:" + "{:<4}".format(str(stats[0])) +
                            " MAGIC:" + "{:<4}".format(str(stats[1])) +
                            " DEF:" + "{:<4}".format(str(stats[2])) + " AP:" +
                            "{:<4}".format(str(stats[3])) + " SwordAbility:" +
                            "{:<20}".format(str(SwordAbility_Modified[1])) +
                            " ShieldAbility:" +
                            "{:<20}".format(str(ShieldAbility_Modified[1])) +
                            " StaffAbility:" +
                            "{:<20}".format(str(StaffAbility_Modified[1])))
                        #EXPNeeded = readAndUnpack(fileBin,4)
                        fileBin.seek(8, 1)  #skip exp and stats
                        if (chars == 0):
                            SwordAbility = readAndUnpack(fileBin, 2)
                            ShieldAbility = readAndUnpack(fileBin, 2)
                            StaffAbility = readAndUnpack(fileBin, 2)
                        else:
                            fileBin.seek(0x6, 1)
                        fileBin.seek(beforeMoving, 0)  #go back to beginning
                        fileBin.seek(4, 1)  #skip exp
                        writeIntOrHex(fileBin, stats[0], 1)  #write stats
                        writeIntOrHex(fileBin, stats[1], 1)
                        writeIntOrHex(fileBin, stats[2], 1)
                        writeIntOrHex(fileBin, stats[3], 1)
                        if (chars == 0):
                            writeIntOrHex(fileBin, SwordAbility_Modified[0], 2)
                            writeIntOrHex(fileBin, ShieldAbility_Modified[0],
                                          2)
                            writeIntOrHex(fileBin, StaffAbility_Modified[0], 2)
                        else:
                            fileBin.seek(0x6, 1)
                        #--Increase stats for next time--
                        #we can only increase 1 or 2 values depending on the ability that is present otherwise the game will not know how to handle it and crash
                        SwordAbility_Modified = emptyTuple
                        ShieldAbility_Modified = emptyTuple
                        StaffAbility_Modified = emptyTuple
                        if (i not in AbilityLevelsNums or chars != 0):
                            statsAmtToRandomize = 2
                        else:
                            #We will randomize the abilities now
                            SwordAbility_Modified = lvlAbilitiesList[0].pop(0)
                            ShieldAbility_Modified = lvlAbilitiesList[1].pop(0)
                            StaffAbility_Modified = lvlAbilitiesList[2].pop(0)
                            statsAmtToRandomize = 1

                        randomStat = [0, 1, 2, 3]
                        endingList = []
                        for x in range(statsAmtToRandomize):
                            randomnum = random.randint(0, len(randomStat) - 1)
                            poppednum = randomStat.pop(randomnum)
                            endingList.append(poppednum)
                        for y in endingList:
                            stats[y] += random.randint(0, 3)
                        #STR = readAndUnpack(fileBin,1)
                        #MAG = readAndUnpack(fileBin,1)
                        #DEF = readAndUnpack(fileBin,1)
                        #AP = readAndUnpack(fileBin,1)

                        fileBin.seek(2, 1)  # skip two bytes
                    fileBin.seek(0x4, 1)  # skip four bytes

            fileBin.close()
Example #16
0
def RandomizeBonusLevels(bonusLevelBool, bonusItemBool, critBonusBool,
                         extraAbilitiesInt, GiveGuard):
    offSetSeed(3)

    def getBonusLevelsFromMSN():
        fileBonuslevels = []
        path = "export/KH2/msn/jp/"
        if PS3Version():
            path = "export/msn/us/"
        msnFileList = getAllFileNamesInFolder(path)
        for msnFile in msnFileList:
            fileBin = open(path + msnFile, 'rb+')
            barOffset = findBarHeader(fileBin)
            fileBin.seek(0x18 + barOffset,
                         0)  # Skip to first header and get pos
            newPos = readAndUnpack(fileBin, 4)
            fileBin.seek(newPos + barOffset, 0)
            fileBin.seek(0xD, 1)
            fileBonuslevels.append(readAndUnpack(fileBin, 1))
            fileBin.close()
        fileBonuslevels = sorted(list(dict.fromkeys(fileBonuslevels)))
        return fileBonuslevels

    if GiveGuard:
        newList = list(
            filter(lambda d: d.code == 0x052, AbilityList[
                AbilityTable_enum.Action]))  # Check for same character
        newList[0].maximum = 0
    if extraAbilitiesInt == 2:  #If user asks for more abilities
        newList = list(
            filter(lambda d: d.character == KHCharacter.Sora, AbilityList[
                AbilityTable_enum.Support]))  # Check for same character
        newList = list(
            filter(lambda d: d.abilitytype == AbilityType.Additive, newList))
        #Grab from level up pool too!
        newList2 = list(
            filter(lambda d: d.character == KHCharacter.Sora, AbilityList[
                AbilityTable_enum.LevelUp]))  # Check for same character
        newList2 = list(
            filter(lambda d: d.abilitytype == AbilityType.Additive, newList2))
        newList = newList + newList2
        for i in range(20):  #Give like 20 more bonus abilities
            itemToCopy = random.choices(newList, k=1)[0]
            itemCopied = copy.deepcopy(itemToCopy)
            itemCopied.abilityLearned = AbilityTypeGained.Normal
            AbilityList[AbilityTable_enum.Support].append(itemCopied)

    if critBonusBool:
        # Randomize critical mode abilities by setting them to normal and grabbing random normal abilities
        newList = list(
            filter(lambda d: d.character == KHCharacter.Sora, AbilityList[
                AbilityTable_enum.Support]))  # Check for same character
        newList = list(
            filter(
                lambda d: d.abilityLearned == AbilityTypeGained.CriticalBonus,
                newList))
        newList = list(filter(lambda d: d.emptyItem(), newList))
        critAbilitiesNum = 0
        for abilityitem in newList:
            critAbilitiesNum += abilityitem.maximum
            abilityitem.abilityLearned = AbilityTypeGained.Normal

        amountOfAbilitiesNum = 0
        while amountOfAbilitiesNum < critAbilitiesNum:
            newList = list(
                filter(lambda d: d.character == KHCharacter.Sora,
                       AbilityList[AbilityTable_enum.Support]))
            newList = list(
                filter(lambda d: d.abilityLearned == AbilityTypeGained.Normal,
                       newList))
            newList = list(filter(lambda d: d.emptyItem(), newList))

            itemsToBonus = random.choice(newList)
            index = AbilityList[AbilityTable_enum.Support].index(itemsToBonus)
            itemsToBonus = AbilityList[AbilityTable_enum.Support][index]
            if itemsToBonus.abilityLearned == AbilityTypeGained.Normal:
                if itemsToBonus.maximum + amountOfAbilitiesNum <= critAbilitiesNum:
                    amountOfAbilitiesNum += itemsToBonus.maximum
                    itemsToBonus.abilityLearned = AbilityTypeGained.CriticalBonus
    #character,type of boost
    CharBoosts = []
    bonusLevelCharData = []
    for i in range(15):
        bonusLevelCharData.append([])
    abilityChoosing = []
    for i in range(15):
        abilityChoosing.append([])
    abilitesForEachChar = []
    for i in range(3):
        abilitesForEachChar.append(0)

    #get number of bonus abilities for each char
    for char in KHCharacter:
        amount = 0
        for type in range(len(AbilityList)):
            if type != AbilityTable_enum.LevelUp:
                for itemAb in AbilityList[type]:
                    if itemAb.character == char and itemAb.abilityLearned == AbilityTypeGained.Normal and itemAb.emptyItem(
                    ):
                        amount += 1
        abilitesForEachChar[char] = amount

    for char in range(3):
        CharBoosts.append([0])
        for type in range(6):
            CharBoosts[char].append(0)
            #HP MP ARMOR ACCESSORY ITEM DRIVE
    maxCharBoosts = [[20, 4, 3, 6, 5, 3], [18, 0, 1, 0, 2, 1],
                     [17, 0, 1, 0, 3, 1]]

    def randomizeABonusLevel(hp, mp, armor, access, item, drive, abilityitem1,
                             abilityitem2, char, bonslevel):
        nonlocal GiveGuard
        oldChar = char
        if char + 1 == 0xE:  # If the character is roxas, change it to sora's num because theyre the same
            char = 0
        hp = mp = armor = drive = item = access = abilityitem2 = abilityitem1 = 0  #Reset all
        currentNotifications = 0
        typeOfAbility = -1
        abilityitem1_name = ""
        abilityitem2_name = ""

        if bonslevel == 0x36:
            currentNotifications = 2  #Do not randomize Stats if the bonus level is 36/ Aerial recovery since it doesnt give that for some reason
            if GiveGuard:
                abilityitem1 = 0x052
                abilityitem1_name = "Guard (Forced)"
        if (BonusLevel not in bonusNumList
            ):  # Blacklist bonus levels not in the game.
            currentNotifications = 2  #
        #handle ability swapping here

        if bonslevel in abilityChoosing[
                char]:  #if the level we are is the same level that was randomly chosen to get an ability randomize by choosing between two ability types

            def filterListQuick(AbilityTp):
                newList = list(
                    filter(lambda d: d.character == char,
                           AbilityList[AbilityTp]))  # Check for same character
                newList = list(
                    filter(
                        lambda d: d.abilityLearned == AbilityTypeGained.Normal,
                        newList))  # Normal abilities only
                newList = list(filter(lambda d: d.emptyItem(),
                                      newList))  # Check if empty ability
                return newList

            abilityChoosing[char].remove(bonslevel)
            possibleChoices = []
            for types in range(2):
                if len(filterListQuick(types)) != 0:
                    possibleChoices.append(types)
            if len(possibleChoices) != 0:
                typeOfAbility = random.choice(possibleChoices)
                newList = filterListQuick(typeOfAbility)
                random.shuffle(newList)
                abilityitem1 = newList[0]
                index = AbilityList[typeOfAbility].index(abilityitem1)
                AbilityList[typeOfAbility][index].subtractQOne(
                )  #subtract cause we're using it
                abilityitem1 = AbilityList[typeOfAbility][index].code
                abilityitem1_name = AbilityList[typeOfAbility][index].name
                currentNotifications += 1

        usedThisRound = [0, 0, 0, 0, 0, 0]
        while currentNotifications < 2:  #Do stat boosts here
            randomizeBoostList = []

            for x in CharacterBoostType:
                if (CharBoosts[char][x] < maxCharBoosts[char][x]
                        and not usedThisRound[x]):
                    randomizeBoostList.append(x)
            if len(randomizeBoostList) != 0:
                slotToRandomize = random.choices(randomizeBoostList, k=1)[0]

                #handle adding to new boosts
                for boosttype in CharacterBoostType:
                    if (slotToRandomize == boosttype):
                        if boosttype == CharacterBoostType.HPBoosts:
                            hp = KHCharacterHPTable[char]
                        if boosttype == CharacterBoostType.MPBoosts:
                            mp = 0xa
                        if boosttype == CharacterBoostType.DriveUpgrades:
                            drive = 1
                        if boosttype == CharacterBoostType.ArmorSlots:
                            armor = 1
                        if boosttype == CharacterBoostType.Items:
                            item = 1
                        if boosttype == CharacterBoostType.Accessory:
                            access = 1
                        usedThisRound[boosttype] = True
                        CharBoosts[char][boosttype] += 1
                        currentNotifications += 1

            else:
                break
        if bonusItemBool and currentNotifications < 2:  # After everything is done and we still have an empty slot, give an bonus item
            tablesToChooseFrom = (kh2rando_itemTable.accessory_table,
                                  kh2rando_itemTable.synthesis_table,
                                  kh2rando_itemTable.item_table)
            weightTable = (0.5, 0.4, 0.8)
            choosenChoice = random.choices(tablesToChooseFrom,
                                           weights=weightTable,
                                           k=1)[0]
            choosenItemKey = random.choice(list(choosenChoice.keys()))
            choosenItem = choosenChoice[choosenItemKey]
            abilityitem2 = choosenItem[3]
            abilityitem2_name = choosenItemKey
            currentNotifications += 1
        if hp == 0 and mp == 0 and armor == 0 and drive == 0 and item == 0 and access == 0 and abilityitem1 == 0 and abilityitem2 == 0:
            alertDebug = 0
        if (BonusLevel in bonusNumList):
            writeOutCome_BonusLevel(
                oldChar, bonslevel, "HP:" + "{:<4}".format(str(hp)) + " MP:" +
                "{:<4}".format(str(mp)) + " ARMOR:" +
                "{:<4}".format(str(armor)) + " DRIVE:" +
                "{:<4}".format(str(drive)) + " ITEM:" +
                "{:<4}".format(str(item)) + " ACCESSORY:" +
                "{:<4}".format(str(access)) + " Ability/Item:" +
                ("{:<20}".format(abilityitem1_name)) + " Ability/Item 2:" +
                ("{:<20}".format(abilityitem2_name)))
        #Returning format might be wrong!!!!
        #hp mp drive?,item?,armor,access
        return (hp, mp, drive, item, armor, access, abilityitem1, abilityitem2)

    if (bonusLevelBool):
        print("Modifying bonus levels...")
        bonusNumList = getBonusLevelsFromMSN()
        if (copyKHFile("00battle.bin")):
            fileBin = open(
                "00battle.bin",
                'rb+')  # skip like 4 hexs because it has useless data lol
            findHeaderinBAR(fileBin, 'bons', True)
            if (fileBin):
                levelBonusStartPos = fileBin.tell(
                )  #gimmie our currentPosition
                fileBin.seek(4, 1)
                amtOfBonusLevels = readAndUnpack(fileBin, 4)  #
                for i in range(
                        amtOfBonusLevels + 1
                ):  #Get the amount of bonus levels for specific characters
                    fileBin.seek(
                        levelBonusStartPos + 8 + (i * 0x10), 0
                    ),  # reset back to original position for writing thats coming up (Plus two to skip bonus level and character)
                    BonusLevel = readAndUnpack(fileBin, 1)  # Bonus level
                    Character = readAndUnpack(
                        fileBin, 1
                    )  # Character value. 01 == sora 02 == donald 03 == goofy ...etc for others
                    if Character == 0xE:  # If the character is roxas, change it to sora's num because theyre the same
                        Character = 1
                    if (BonusLevel != 0x36 or not GiveGuard):
                        if (
                                BonusLevel in bonusNumList
                        ):  #Make sure the bonus level is actually used ingame.
                            bonusLevelCharData[Character -
                                               1].append(BonusLevel)
                #now that we have data, choose ability locations throughout the bonuses

                for char in KHCharacter:
                    for choicenum in range(abilitesForEachChar[char]):
                        newChoice = random.choice(bonusLevelCharData[char])
                        popout = bonusLevelCharData[char].pop(
                            bonusLevelCharData[char].index(newChoice))
                        abilityChoosing[char].append(popout)

                randomBonusLevelLoop = list(range(amtOfBonusLevels + 1))
                random.shuffle(
                    randomBonusLevelLoop
                )  # We will randomize the order we go through chests in in order to be a bit more random. Kinda odd but yea so we evenly spread out priority items instead of like in a row.

                for i in randomBonusLevelLoop:
                    fileBin.seek(
                        levelBonusStartPos + 8 + (i * 0x10), 0
                    ),  # reset back to original position for writing thats coming up (Plus two to skip bonus level and character)
                    BonusLevel = readAndUnpack(fileBin, 1)  # Bonus level
                    Character = readAndUnpack(
                        fileBin, 1
                    )  # Character value. 01 == sora 02 == donald 03 == goofy ...etc for others
                    HPVal = readAndUnpack(fileBin, 1)  # HP Value.
                    MPVal = readAndUnpack(fileBin, 1)  # MP Value.
                    SlotUpgrades_Armor = readAndUnpack(
                        fileBin, 1)  # Slot upgrade to player or party member
                    SlotUpgrades_Accessory = readAndUnpack(
                        fileBin, 1)  # Slot upgrades to player or party member
                    SlotUpgrades_Item = readAndUnpack(
                        fileBin, 1)  # Slot upgrades to player or party member
                    SlotUpgrades_Drive = readAndUnpack(
                        fileBin, 1)  # Slot upgrades to player or party member
                    AbilityItem1 = readAndUnpack(
                        fileBin,
                        2)  # Ability upgrades to player or party member
                    AbilityItem2 = readAndUnpack(
                        fileBin,
                        2)  # Ability upgrades to player or party member
                    fileBin.seek(levelBonusStartPos + 8 + 2 + (i * 0x10), 0)
                    if (Character >= 1 and Character < 4 or Character == 0xE):
                        newbonusLevelVal = randomizeABonusLevel(
                            HPVal, MPVal, SlotUpgrades_Armor,
                            SlotUpgrades_Drive, SlotUpgrades_Item,
                            SlotUpgrades_Accessory, AbilityItem1, AbilityItem2,
                            Character - 1, BonusLevel)
                        for y in range(6):
                            writeIntOrHex(fileBin, newbonusLevelVal[y],
                                          1)  #write hp,mp,slot,slot,slot,slot
                        writeIntOrHex(fileBin, newbonusLevelVal[6],
                                      2)  # write ability
                        writeIntOrHex(fileBin, newbonusLevelVal[7],
                                      2)  # write ability

                fileBin.close()
def randomizeMusic(ranMusic):
    if ranMusic:
        offSetSeed(50)
        print("Modifying music...")
        path = "export/KH2/ard"
        if PS3Version():
            path = "export/ard/us"
        fileList = getAllFileNamesInFolder(path)
        for j in fileList:
            musicOccurenceNum = 0
            musicListUsed= []
            filename = j
            currentWorld = filename[0:2].upper()
            currentRoom = int(filename[2:4])
            # shutil.copyfile(path+ "/" +filename, "ard/"+filename) #Move to native folder
            regionExtraFolder = ""
            if PS3Version():
                regionExtraFolder = "us/"
            filename = "ard/"+regionExtraFolder + filename
            if copyKHFile(filename):
                writeRandomizationLog(filename)
                fileBin = open(filename, 'rb+')
                """
                        Notes:
                        Affecting music data also affects the space of ram. Great. Some places may softlock because of this.....
                        Another music weighting system based on file size?
                        
                        EVT Data: Amt of entries not given. Size of entries not given. 
                        Anything after the evt bar entry in the main header will be in evt, btl header sometimes 
                        Start of EVT entry depending on event type:
                        Event ID, Used by a general event. EX: Bosses with their respective cutscene on death/enter
                        Empty?
                        Event 2ndID, Possibly a type? Changes and isnt very consistent.

                        Event 2ndID's when a boss is assigned to an eventId may be:
                        2C if 48 (Super Boss?)
                        22 if 44 (Normal Boss?)
                        possibly use an if statement if an value is above an amount
                        Music event starts with 10 00 01? Wow, what a waste of time trying to decipher this
                        5 Unknown Bytes,
                        Music Num Data, 0C == Current World music? 09 == Current World Battle Music?
                        Empty,
                        Music Num Data,

                        FF Sometimes ends the data, sometimes it doesn't.
                """
                if findHeaderinBAR(fileBin, 'evt', False):
                    fileBin.seek(0x8, 1)
                    evtSize = readAndUnpack(fileBin, 4)
                    """ Useless
                    eventIDList = []
                    if findHeaderinBAR(fileBin, 'map', False):
                        fileBin.seek(0x8, 1)
                        mapSize = readAndUnpack(fileBin, 4)
                        findHeaderinBAR(fileBin, 'map', True)  # go back and start going through
                        filePosition = fileBin.tell()
                        mapFileText = fileBin.read(mapSize)
                        fileBin.seek(filePosition, 0)
                        difBytes = [b'\x01\x00\x02']
                        for differentEvtTypes in difBytes:
                            curPos = 0
                            while (mapFileText.count(differentEvtTypes, curPos) != 0):
                                curPos = mapFileText.find(differentEvtTypes, curPos)  # Skip 5 bytes
                                fileBin.seek(filePosition + curPos, 0)
                                fileBin.seek(-0x4, 1)  # Go back, find 2nd id
                                eventIDList.append(readUnpackGoBack(fileBin, 1))
                                curPos += 1
                        if len(eventIDList) != 0:
                            debughi = 0
                    """
                    findHeaderinBAR(fileBin, 'evt', True)  # go back and start going through
                    filePosition = fileBin.tell()
                    evtFileText = fileBin.read(evtSize)
                    fileBin.seek(filePosition, 0)

                    difBytes = [b'\x10\x00\x01']

                    for differentEvtTypes in difBytes:
                        curPos = 0
                        while (evtFileText.count(differentEvtTypes, curPos) != 0):
                            curPos = evtFileText.find(differentEvtTypes, curPos)  # Skip 5 bytes
                            fileBin.seek(filePosition + curPos, 0)
                            if not CheckIfMusicBlackList(currentWorld,currentRoom,musicOccurenceNum):
                                fileBin.seek(-0x4, 1)  # Go back, find 2nd id
                                evtFirstEventID = readAndUnpack(fileBin, 1)
                                fileBin.seek(1, 1)
                                evtSecondEventID = readAndUnpack(fileBin, 1)
                                fileBin.seek(1, 1)
                                fileBin.seek(len(differentEvtTypes), 1)  # skip over what we just found
                                fileBin.seek(0x1, 1)  # skip empty
                                firstMusicID = readUnpackGoBack(fileBin, 1)
                                random.shuffle(musicList)
                                chooseNewMusic = musicList[0]
                                for xd in musicListUsed:
                                    if evtFirstEventID == xd[0]:
                                        chooseNewMusic =xd[1]
                                writeIntOrHex(fileBin, chooseNewMusic, 1)
                                fileBin.seek(0x1, 1)  # skip empty
                                firstMusicID2 = readUnpackGoBack(fileBin, 1)
                                writeIntOrHex(fileBin, chooseNewMusic, 1)
                                usedOnce = False
                                for xd in musicListUsed:
                                    if evtFirstEventID == xd[0]:
                                        usedOnce = True
                                if not usedOnce:
                                    musicListUsed.append((evtFirstEventID,chooseNewMusic))
                            curPos += 1
                            musicOccurenceNum+=1
                fileBin.close()
                                        def enemyBTLMSNEdit():
                                            #PS3 Version Note: Little Endian to Big Endian change: every 2 bytes is swapped. GREAT.
                                            #Bytearray=  "BB"[::-1] + "50"[::-1] + "M_"[::-1] + "1S"[::-1] + "40"[::-1] +".B"[::-1]
                                            """
                                            def replaceAllMSN(): #very destructive, has problems with ard files that has multiple bosses
                                                nonlocal x
                                                # write new mission file
                                                BeforeReplaced = fileBin.read(18)  # i assume 18 is the most?????
                                                fileBin.seek(0, 0)

                                                replace1 = BeforeReplaced.decode('utf-8').rstrip('\x00')
                                                strLength = len(bossMSNTable[x])
                                                strLength2 = len(replace1)
                                                spacingNum = strLength2 - strLength
                                                beforeEncode = bossMSNTable[x]
                                                beforeEncode = msnFileCreate(beforeEncode, currentWorld, currentRoom)

                                                for x in range(spacingNum):
                                                    beforeEncode += '\x00'
                                                for x in range(-spacingNum):
                                                    replace1 += '\x00'

                                                replace2 = str.encode(beforeEncode)
                                                replace1 = str.encode(replace1)
                                                # note: we should add extra bytes based on length so we dont offset the file if we replace stuff
                                                allData = fileBin.read()
                                                allData = allData.replace(replace1, replace2)  # oh my god i forget to store it back and i was wondering why it wasnt working
                                                fileBin.seek(0, 0)
                                                fileBin.write(allData)
                                            """
                                            def replaceOneMSN(newMSN):
                                                # write new mission file
                                                BeforeReplaced = fileBin.read(0x20)  # i assume 18 is the most?????
                                                BeforeReplaced = BeforeReplaced.decode('utf-8').rstrip('\x00')
                                                BeforeReplaced = ReverseEndianString(BeforeReplaced,2,True)
                                                fileBin.seek(-0x20, 1)

                                                beforeEncode = msnFileCreate(newMSN,currentWorld,currentRoom,BeforeReplaced)

                                                """
                                                All of this doesn't work when trying to fix Final Xemnas MSN softlocking. Great.
                                                exportFolderName = "msn/jp/"
                                                if PS3Version():
                                                    exportFolderName = "msn/us/"
                                                fileBin_MSN = open(exportFolderName + beforeEncode+'.bar','rb+')
                                                findHeaderinBAR(fileBin_MSN,newMSN[:4],True)
                                                fileBin_MSN.write(bytearray([0x00, 0x02, 0x01 ,0x11 ,0x11 ,0x71]))
                                                findHeaderinBAR(fileBin_MSN, newMSN[:4], False)
                                                fileBin_MSN.seek(0x4+0x4,1)
                                                barSize = readAndUnpack(fileBin_MSN,4)
                                                findHeaderinBAR(fileBin_MSN, newMSN[:4], True)
                                                fileBin_MSN.seek(barSize,1)
                                                beforePos = fileBin_MSN.tell()
                                                findHeaderinBAR(fileBin_MSN,newMSN[:4],False)
                                                fileBin_MSN.seek(0x10 + 0x4,1) #Skip down an entry and move to New location
                                                newPos = readAndUnpack(fileBin_MSN,4)
                                                offsetPos = findBarHeader(fileBin_MSN)
                                                fileBin_MSN.seek(newPos+offsetPos,0)
                                                writingString = 'eh20_ms113'.ljust(0x10,'\x00').encode() #Write new mission objective
                                                fileBin_MSN.write(writingString)
                                                fileBin_MSN.close()
                                                appendToSpecificPos(exportFolderName + beforeEncode+'.bar',beforePos,newMSN[:4],bytearray([0x08, 0xD1, 0x00, 0x04 ,0x00 ,0x00, 0x00, 0x00]))
                                                """

                                                beforeEncode = ReverseEndianString(beforeEncode, 2, True,True)
                                                spacingNum = 0x20 - len(beforeEncode)
                                                # note: we should add extra bytes based on length so we dont offset the file if we replace stuff
                                                for x in range(spacingNum):
                                                    beforeEncode += '\x00'

                                                replace2 = str.encode(beforeEncode)
                                                fileBin.write(replace2)
                                                fileBin.seek(-len(replace2), 1) #Write, go back and we're done.





                                            #eh20_ms113 == replace ms_boss if the final boss mission is being replaced EH20_MS113.bar
                                            #end of utility functions. start of main function
                                            #This maybe need to be looked at again.
                                            btl_String = 'btl'
                                            findHeaderinBAR(fileBin,btl_String,True)
                                            # find "btl" header thing
                                            # go to position from the btl header
                                            endcodedCheck = ReverseEndianString(check,2,True).encode('utf-8')  # get entry name ex: b_00
                                            posBeforeRead = fileBin.tell()
                                            data2 = fileBin.read()

                                            seekToRead = data2.find(endcodedCheck)
                                            fileBin.seek(posBeforeRead, 0)
                                            fileBin.seek(seekToRead, 1)
                                            # goto name closest
                                            # find original msn by backing up a lil so we find the currentworld string
                                            posBeforeRead = fileBin.tell()
                                            seekToRead = -1
                                            offset = 0
                                            #15 00 09 find this byte and offset foward by 4 bytes and write this way
                                            while seekToRead != 0:  # This is slow..... But the best I can do ATM.
                                                fileBin.seek(posBeforeRead, 0)
                                                offset += 1
                                                if offset > 300:
                                                    return #We probrably can't find anything because an boss has already taken its place. In this case, we will just stop the function
                                                fileBin.seek(fileBin.tell() - offset, 0)
                                                data3 = fileBin.read()
                                                findThing =data3.find(b'\x15\x00\x09')
                                                if findThing == 0:
                                                    seekToRead = findThing+3+4 #Skip the byte we found and the following 4 bytes to get to the string
                                                    break;
                                            fileBin.seek(seekToRead, 1)
                                            fileBin.seek(posBeforeRead, 0)
                                            fileBin.seek(-offset, 1)
                                            offset = 0
                                            if not PS3Version():
                                                offset = 1
                                            fileBin.seek(seekToRead+offset, 1)
                                            testRead = fileBin.read(0x20)
                                            testRead = ReverseEndianString(testRead.decode('utf-8'),2,True).rstrip('\x00')
                                            fileBin.seek(-0x20, 1)
                                            if not testRead == 'EH20_MS113':  # Final Xemnas Specific dont edit
                                                if  testRead== "HB38_FM_MAR" or testRead == 'CA01_MS204': #Replace Marluxia MSN as it softlocks at the start of battle and Grim Reaper Mission cause it crashes on PS3
                                                    replaceOneMSN("HB33_FM_LAR") #Generic Battle MSN file
                                                    enemyBTLMSNEdit()  # Try again......
                                                else:
                                                    for x in bossMSNTable:
                                                        if enemyToWrite.code == x:
                                                            replaceOneMSN(bossMSNTable[x])
Example #19
0
def randomizeEquipmentStats(randomEquipStat, randomEquipAbility):
    offSetSeed(8)
    if (randomEquipStat or randomEquipAbility):
        print("Randomizing equipment stats...")
        if (copyKHFile("03system.bin")):
            fileBin = open("03system.bin", "rb+")
            if (fileBin):
                findHeaderinBAR(fileBin, 'item', True)

                #Size 0x18
                fileBin.seek(4, 1)  #Skip ??
                entryAmt = readAndUnpack(fileBin, 4)
                entryPos = fileBin.tell()
                StatusEffectIdList = []
                for x in range(entryAmt):
                    fileBin.seek(entryPos + (x * 0x18), 0)
                    ItemID = readAndUnpack(fileBin, 2)
                    CategoryID = readAndUnpack(
                        fileBin, 1
                    )  #This is really conflicting. Sometimes the status ID is only 2 bytes away and sometimes its 4. :<
                    if CategoryID == 0x0E or CategoryID == 0x0F:  #If armor or accessory
                        fileBin.seek(1, 1)
                    elif CategoryID == 0x02 or CategoryID == 0x03 or CategoryID == 0x04:  #If keyblade/shield/staff
                        fileBin.seek(3, 1)
                    else:
                        continue  #Skip, we dont want any other item if it isnt an armor, accessory or keyblade/weapon
                    StatusID = readAndUnpack(fileBin, 2)
                    StatusEffectIdList.append((StatusID, ItemID))

                RealStatusItems = [
                ]  #if the item matches up with an equipment, accessory or armor item we will add it to the list along with its object for later reference
                for itemThing in StatusEffectIdList:
                    for itemReal in newItemList:
                        if itemReal.code == itemThing[1] and itemThing[0] != 0:
                            RealStatusItems.append((itemThing[0], itemReal))

                fileBin.seek(entryPos + (entryAmt * 0x18), 0)
                statusModifier = []
                for whatever in range(12):
                    statusModifier.append(0)
                fileBin.seek(4, 1)
                statusAmt = readAndUnpack(fileBin, 4)  #I counted
                statusPos = fileBin.tell()
                for x in range(statusAmt):
                    statusPos_Entry = fileBin.tell()
                    statsID = readAndUnpack(fileBin, 2)
                    abilityID = readAndUnpack(fileBin, 2)
                    for d in range(12):
                        statusModifier[d] = readAndUnpack(fileBin, 1)

                    #Modify
                    ifinStatusItem = False
                    itemToUse = None
                    for xd in RealStatusItems:
                        if xd[0] == statsID:
                            itemToUse = xd[1]
                            ifinStatusItem = True
                            break

                    if ifinStatusItem:
                        fileBin.seek(statusPos_Entry + 2, 0)
                        if randomEquipAbility:
                            if itemToUse.type == itemType.Equipment or (
                                    itemToUse.type == itemType.Accessory
                                    and random.randint(0, 5) > 4
                            ):  #If the player is lucky, an ability is added.
                                abilityID = random.choice(newAbilityList).code
                        if randomEquipStat:
                            if itemToUse.type == itemType.Equipment or itemToUse.type == itemType.Accessory:
                                chanceList = [
                                    random.randint(1, 6),
                                    random.randint(1, 10),
                                    random.randint(0, 10)
                                ]
                                chanceList_Weight = [0.3, 0.5, 0.2]
                                newRando = random.choices(
                                    chanceList, k=1,
                                    weights=chanceList_Weight)[0]
                                chanceList = [
                                    random.randint(1, 6),
                                    random.randint(1, 10),
                                    random.randint(0, 10)
                                ]
                                newRando2 = random.choices(
                                    chanceList, k=1,
                                    weights=chanceList_Weight)[0]
                                statusModifier[
                                    EquipmentStats.StrengthStat] = newRando
                                statusModifier[
                                    EquipmentStats.MagicStat] = newRando2
                            if itemToUse.type == itemType.Accessory:
                                chanceList = [
                                    random.randint(1, 30),
                                    random.randint(1, 10),
                                    random.randint(0, 10)
                                ]
                                chanceList_Weight = [0.3, 0.5, 0.2]
                                newRando = random.choices(
                                    chanceList, k=1,
                                    weights=chanceList_Weight)[0]
                                statusModifier[
                                    EquipmentStats.APStat] = newRando
                            if itemToUse.type == itemType.Armor:
                                chanceList = [
                                    random.randint(1, 5),
                                    random.randint(1, 4),
                                    random.randint(0, 10)
                                ]
                                chanceList_Weight = [0.3, 0.5, 0.2]
                                newRando = random.choices(
                                    chanceList, k=1,
                                    weights=chanceList_Weight)[0]
                                statusModifier[
                                    EquipmentStats.DefenseStat] = newRando
                                for resistNums in range(4, 9):
                                    statusModifier[resistNums] = random.randint(
                                        75, 150
                                    )  #Not too OP, but gives the chance of reducing resistance
                                #for resistNums in range(9,10): #Global resist and invisible stuff so dont go too crazy
                                #statusModifier[resistNums] = random.randint(80,120)
                        writeIntOrHex(fileBin, abilityID, 2)
                        for d in range(12):
                            writeIntOrHex(fileBin, statusModifier[d], 1)