def mod_texture(asset, img, load_path, name, templ_pathid, comp='dxt1'): path_id = max(asset.objects.keys()) + 1 # construct texture object obj = ObjectInfo(asset) obj.path_id = path_id obj.type_id = 28 obj.class_id = 28 obj.is_destroyed = False obj._contents = Texture2D(FFOrderedDict(0)) for k, v in asset.objects[templ_pathid].contents._obj.items(): obj._contents._obj[k] = v asset.objects[path_id] = obj # load image obj._contents.name = name obj._contents.height = img.height obj._contents.width = img.width # DXT1 or DXT5 obj._contents.format = 12 if comp == 'dxt5' else 10 img.flip() # load image as DDS, stripping 128-byte header obj._contents.data = img.make_blob(comp)[128:] ab_index, preload_index = add2assetbundle(asset, load_path, path_id) print('inserted texture.\n\tpath_id: {}, ab_index: {}, preloadIndex: {}'. format(path_id, ab_index, preload_index))
def mod_tabledata(tabledata): itemtable = tabledata.objects[7].contents['m_p' + ITEM_TYPE + 'ItemTable'] itemid = len(itemtable['m_pItemData']) assert len(itemtable['m_pItemData']) == len(itemtable['m_pItemStringData']) # construct item object fromtempl(itemtable['m_pItemData'], TEMPL_ITEMID, itemid) # fix item id itemtable['m_pItemData'][itemid]['m_iItemNumber'] = itemid itemtable['m_pItemData'][itemid]['m_iItemName'] = itemid itemtable['m_pItemData'][itemid]['m_iComment'] = itemid # configure properties itemtable['m_pItemData'][itemid]['m_iDefenseRat'] = ITEM_DEFENSE # ...and any other changes you want # construct item strings object fromtempl(itemtable['m_pItemStringData'], TEMPL_ITEMID, itemid) # set strings itemtable['m_pItemStringData'][itemid]['m_strName'] = ITEM_NAME itemtable['m_pItemStringData'][itemid]['m_strComment'] = ITEM_COMMENT meshid = len(itemtable['m_pItemMeshData']) templ_meshid = itemtable['m_pItemData'][TEMPL_ITEMID]['m_iMesh'] itemtable['m_pItemData'][itemid]['m_iMesh'] = meshid # construct item mesh info object fromtempl(itemtable['m_pItemMeshData'], templ_meshid, meshid) itemtable['m_pItemMeshData'][meshid][ 'm_pstrMTextureString'] = ITEM_TEXTURE_NAME # female texture # itemtable['m_pItemMeshData'][meshid]['m_pstrFTextureString'] = ITEM_TEXTURE_NAME iconnum = findnexticon(tabledata, 3) # construct icon object iconid = len(itemtable['m_pItemIconData']) itemtable['m_pItemIconData'].append(FFOrderedDict(0)) itemtable['m_pItemIconData'][iconid]['m_iIconType'] = 3 itemtable['m_pItemIconData'][iconid]['m_iIconNumber'] = iconnum itemtable['m_pItemData'][itemid]['m_iIcon'] = iconid print( 'added itemid {} to tabledata.\n\tmeshid: {}, iconid: {}, iconum: {}'. format(itemid, meshid, iconid, iconnum)) return iconnum
def createQuestItem(name): index = len(questItemData) itemString = FFOrderedDict(0) for k, v in questItemStringData[0].items(): itemString[k] = v itemString['m_strName'] = name itemString['m_strComment'] = name questItemStringData.append(itemString) item = FFOrderedDict(0) for k, v in questItemData[0].items(): item[k] = v item['m_iIcon'] = 2 # Probably unneeded but every item has this icon item['m_iItemName'] = index item['m_iItemNumber'] = index item['m_iItemComment'] = index questItemData.append(item) return index
def createJournalEntry(taskDesc): entry = FFOrderedDict(0) for k, v in journalData[0].items(): entry[k] = v entry['m_iDetaileMissionDesc'] = MISSION_DESCRIPTION entry['m_iMissionCompleteSummary'] = MISSION_COMPLETE_SUMMARY entry[ 'm_iDetaileMissionCompleteSummary'] = NPC_MISSION_COMPLETE_SUMMARY entry['m_iDetailedTaskDesc'] = createMissionString(taskDesc) entry['m_iMissionSummary'] = MISSION_SUMMARY journalData.append(entry) return len(journalData) - 1
def add2assetbundle(asset, path, path_id): ab = asset.objects[1].contents ab_index = len(ab['m_Container']) preload_index = max([x[1]['preloadIndex'] for x in ab['m_Container']]) + 1 ptr = ObjectPointer(None, asset) # type argument is unused ptr.file_id = 0 ptr.path_id = path_id abdata = FFOrderedDict(0) abdata['preloadIndex'] = preload_index abdata['preloadSize'] = 1 abdata['asset'] = ptr ab['m_Container'].append((path, abdata)) return ab_index, preload_index
def createMissionString(string): entry = FFOrderedDict(0) entry['m_pstrNameString'] = string missionStringData.append(entry) return len(missionStringData) - 1
def main(tabledata): # Helper functions def createMissionString(string): entry = FFOrderedDict(0) entry['m_pstrNameString'] = string missionStringData.append(entry) return len(missionStringData) - 1 MISSION_DESCRIPTION = createMissionString(MISSION_DESCRIPTION_TEXT) MISSION_COMPLETE_SUMMARY = createMissionString( MISSION_COMPLETE_SUMMARY_TEXT) NPC_MISSION_COMPLETE_SUMMARY = createMissionString( NPC_MISSION_COMPLETE_SUMMARY_TEXT) MISSION_SUMMARY = createMissionString(MISSION_SUMMARY_TEXT) def createJournalEntry(taskDesc): entry = FFOrderedDict(0) for k, v in journalData[0].items(): entry[k] = v entry['m_iDetaileMissionDesc'] = MISSION_DESCRIPTION entry['m_iMissionCompleteSummary'] = MISSION_COMPLETE_SUMMARY entry[ 'm_iDetaileMissionCompleteSummary'] = NPC_MISSION_COMPLETE_SUMMARY entry['m_iDetailedTaskDesc'] = createMissionString(taskDesc) entry['m_iMissionSummary'] = MISSION_SUMMARY journalData.append(entry) return len(journalData) - 1 # Create reward reward = FFOrderedDict(0) for k, v in rewardData[0].items(): reward[k] = v if isinstance(v, list): reward[k] = [0] * len(v) reward['m_iMissionRewardID'] = len(rewardData) reward['m_iCash'] = REWARD_TAROS reward['m_iFusionMatter'] = REWARD_FM for i in range(min(4, len(REWARD_ITEM_TYPES))): reward['m_iMissionRewarItemType'][i] = REWARD_ITEM_TYPES[i] reward['m_iMissionRewardItemID'][i] = REWARD_ITEMS[i] rewardData.append(reward) # Create mission nameId = createMissionString(MISSION_NAME) maxMissionId = 0 for data in missionData: if data['m_iHMissionID'] > maxMissionId: maxMissionId = data['m_iHMissionID'] missionId = maxMissionId + 1 maxTaskId = 0 for data in missionData: if data['m_iHTaskID'] > maxTaskId: maxTaskId = data['m_iHTaskID'] maxTaskId = maxTaskId + 1 lastNonInstanceTask = maxTaskId def addMissionData(mission, taskInfo): for k, v in missionData[0].items(): mission[k] = v if isinstance(v, list): mission[k] = [0] * len(v) mission['m_iHMissionName'] = nameId mission['m_iHJournalNPCID'] = taskInfo['journalNPC'] mission['m_iHMissionID'] = missionId mission['m_iHMissionType'] = MISSION_TYPE mission['m_iHDifficultyType'] = MISSION_DIFFICULTY mission['m_iCTRReqLvMin'] = REQUIRED_LEVEL mission['m_iHTaskType'] = taskInfo['taskType'] mission['m_iHCurrentObjective'] = createMissionString( taskInfo['objective']) if 'initialMessage' in taskInfo: mission['m_iSTMessageType'] = taskInfo['initialMessage']['type'] mission['m_iSTMessageTextID'] = createMissionString( taskInfo['initialMessage']['text']) mission['m_iSTMessageSendNPC'] = taskInfo['initialMessage']['npc'] if 'initialDialog' in taskInfo: mission['m_iSTDialogBubble'] = createMissionString( taskInfo['initialDialog']['text']) mission['m_iSTDialogBubbleNPCID'] = taskInfo['initialDialog'][ 'npc'] if 'successMessage' in taskInfo: mission['m_iSUMessageType'] = taskInfo['successMessage']['type'] mission['m_iSUMessagetextID'] = createMissionString( taskInfo['successMessage']['text']) # lowercase t 🙄 mission['m_iSUMessageSendNPC'] = taskInfo['successMessage']['npc'] if 'successDialog' in taskInfo: mission['m_iSUDialogBubble'] = createMissionString( taskInfo['successDialog']['text']) mission['m_iSUDialogBubbleNPCID'] = taskInfo['successDialog'][ 'npc'] if 'startItems' in taskInfo: for i in range(min(3, len(taskInfo['startItems']['items']))): mission['m_iSTItemID'][i] = taskInfo['startItems']['items'][i] mission['m_iSTItemNumNeeded'][i] = taskInfo['startItems'][ 'count'][i] if taskInfo['taskType'] != 5: # If there are no mob drops just throw these values instead just for fun (Putting them in CSUItems makes the counter show up on the UI) mission['m_iCSUItemID'][i] = taskInfo['startItems'][ 'items'][i] mission['m_iCSUItemNumNeeded'][i] = taskInfo['startItems'][ 'count'][i] if 'successItems' in taskInfo: for i in range(min(3, len(taskInfo['successItems']['items']))): mission['m_iSUItem'][i] = taskInfo['successItems']['items'][i] mission['m_iSUInstancename'][i] = taskInfo['successItems'][ 'count'][i] if 'failItems' in taskInfo: for i in range(min(3, len(taskInfo['failItems']['items']))): mission['m_iFItemID'][i] = taskInfo['failItems']['items'][i] mission['m_iFItemNumNeeded'][i] = taskInfo['failItems'][ 'count'][i] for i in range(min(2, len(MISSION_PREREQS))): mission['m_iCSTReqMission'][i] = MISSION_PREREQS[i] journalId = createJournalEntry(taskInfo['taskDesc']) mission['m_iSTJournalIDAdd'] = journalId mission[ 'm_iSUJournaliDAdd'] = journalId # NOTE in some missions these are different? but it's a pretty useless thing # TODO implement task type 6 - escorts if taskInfo['taskType'] == 1 or taskInfo['taskType'] == 3 or taskInfo[ 'taskType'] == 4: mission['m_iHTerminatorNPCID'] = taskInfo['targetNPC'] mission['m_iSTGrantWayPoint'] = taskInfo['targetNPC'] elif taskInfo['taskType'] == 2: mission['m_iHTerminatorNPCID'] = taskInfo['target'] mission['m_iSTGrantWayPoint'] = taskInfo[ 'waypoint'] # Different in the case of entering fusion lairs; waypoint is for portal but actual target is inside the lair elif taskInfo['taskType'] == 5: if 'mobCount' in taskInfo: for i in range(min(3, len(taskInfo['mobs']))): mission['m_iCSUEnemyID'][i] = taskInfo['mobs'][i] mission['m_iCSUNumToKill'][i] = taskInfo['mobCount'][i] else: mission['m_iCSUEnemyID'][0] = taskInfo['mobs'][0] for i in range(min(3, len(taskInfo['drops']))): mission['m_iCSUItemID'][i] = taskInfo['drops'][i] mission['m_iCSUItemNumNeeded'][i] = taskInfo['dropNum'][i] mission['m_iSTItemDropRate'][i] = taskInfo['dropRates'][i] elif taskInfo['taskType'] == 6: mission['m_iCSUDEFNPCAI'] = 6 mission['m_iCSUDEFNPCID'] = taskInfo['escortNPC'] for i in range(len(TASK_DATA)): taskInfo = TASK_DATA[i] mission = FFOrderedDict(0) addMissionData(mission, taskInfo) mission['m_iHTaskID'] = maxTaskId + i if 'timer' in taskInfo: mission['m_iSTGrantTimer'] = taskInfo['timer'] mission['m_iCSUCheckTimer'] = taskInfo['timer'] failMission = FFOrderedDict(0) addMissionData(failMission, taskInfo['failTask']) maxTaskId = maxTaskId + 1 # Failure task will be next, all tasks after are pushed down an index failMission['m_iHTaskID'] = maxTaskId + i mission['m_iFOutgoingTask'] = maxTaskId + i failMission[ 'm_iSUOutgoingTask'] = maxTaskId + i - 1 # Return to previous task, no +1 because maxTaskId was incremented missionData.append(failMission) if 'reqInstance' in taskInfo: mission['m_iRequireInstanceID'] = taskInfo['reqInstance'] if mission['m_iFOutgoingTask'] != 0: mission['m_iFOutgoingTask'] = lastNonInstanceTask else: lastNonInstanceTask = maxTaskId + i if i == 0: mission['m_iHNPCID'] = GIVER_ID if i == len(TASK_DATA) - 1: mission['m_iSUReward'] = reward['m_iMissionRewardID'] for i in range(min(4, len(MISSION_COMPLETE_BARKERS))): mission['m_iHBarkerTextID'][i] = createMissionString( MISSION_COMPLETE_BARKERS[i]) else: mission['m_iSUOutgoingTask'] = maxTaskId + i + 1 missionData.append(mission) with open(TABLEDATA_PATH + '_new', 'wb') as f: tabledata.save(f)
def fromtempl(table, src, dst): table.append(FFOrderedDict(0)) for k, v in table[src].items(): table[dst][k] = v