Frankelstner Posted November 15, 2011 Report Share Posted November 15, 2011 (edited) Note: The guid-resolving (and thus much better) version is found here: http://www.bfeditor.org/forums/index.php?showtopic=15531&view=findpost&p=106219 Here's an improved version. Please download http://www.gamefront.com/files/22080360/floattostring_rar and place it in the main Python folder for a better float representation. This version requires the user to provide an output directory (default is C:/bf3 files). This time around the file names will always be read correctly (instead of just 95% of the time) and small numbers will be displayed too instead of just being rounded to zero. Also, the general syntax has been slightly changed (it makes more sense this time around). Drag and drop the folder onto the script file. Here's my work in progress text/gameplay file converter. It converts all binary text files in the folder of the script. It reads everything without issues, though the layout is a bit cumbersome. A file format analysis can be found here: http://www.bfeditor.org/forums/index.php?showtopic=15531&view=findpost&p=105293 #requires Python 2.7 import string import sys from binascii import hexlify from struct import unpack import os from cStringIO import StringIO #adjust output folder here; you must specify a folder outputFolder="C:/bf3 files" try: #try to print a number as 0.95 from ctypes import * floatlib = cdll.LoadLibrary("floattostring") def formatfloat(num): bufType = c_char * 100 buf = bufType() bufpointer = pointer(buf) floatlib.convertNum(c_double(num), bufpointer, 100) rawstring=(buf.raw)[:buf.raw.find("\x00")] if rawstring[:2]=="-.": return "-0."+rawstring[2:] elif rawstring[0]==".": return "0."+rawstring[1:] elif "e" not in rawstring and "." not in rawstring: return rawstring+".0" return rawstring except: #the number will be printed as 0.949999988079 def formatfloat(num): return str(num) def hasher(keyword): #32bit FNV-1 hash with FNV_offset_basis = 5381 and FNV_prime = 33 hash = 5381 for byte in keyword: hash = (hash*33) ^ ord(byte) return hash & 0xffffffff # use & because Python promotes the num instead of intended overflow class Header: def __init__(self,varList): ##all 4byte unsigned integers self.absStringOffset = varList[0] ## absolute offset for string section start self.lenStringToEOF = varList[1] ## length from string section start to EOF self.numGUID = varList[2] ## number of external GUIDs self.null = varList[3] ## 00000000 self.numInstanceRepeater = varList[4] self.numComplex = varList[5] ## number of complex entries self.numField = varList[6] ## number of field entries self.lenName = varList[7] ## length of name section including padding self.lenString = varList[8] ## length of string section including padding self.numArrayRepeater = varList[9] self.lenPayload = varList[10] ## length of normal payload section; the start of the array payload section is absStringOffset+lenString+lenPayload class FieldDescriptor: #field has 4byte hash, 2byte type, 2byte reference/pointer, 4byte offset , 4byte secondary offset #e.g. 4B1F9065 3500 0000 0C000000 1C000000 # hash type ref offset offset2 # => 'VoiceOverType', 0x0035, 0, 12, 28 def __init__(self,varList): self.name = keywordDict[varList[0]] self.type = varList[1] self.ref = varList[2] #the field may contain another complex self.offset = varList[3] #offset in payload section; relative to the complex containing it self.secondaryOffset = varList[4] class ComplexDescriptor: #complex has 4byte hash, 4byte field index, 1byte number of fields, 1byte alignment size, 2byte type, 2byte payload size, 2byte size2 #e.g. 39E97F28 52000000 04 04 3500 5000 0000 # hash fieldIndex num align type size size2 # => 'EntityVoiceOverInfo', 82, 4, 4, 0x0035, 80, 0 def __init__(self,varList): self.name = keywordDict[varList[0]] self.fieldStartIndex = varList[1] #the index of the first field belonging to the complex self.numField = varList[2] #the total number of fields belonging to the complex self.alignment = varList[3] self.type = varList[4] self.size = varList[5] #total length of the complex in the payload section self.secondarySize = varList[6] #seems deprecated class InstanceRepeater: def __init__(self,varList): self.null = varList[0] #seems to be always null self.repetitions = varList[1] #number of instance repetitions self.complexIndex = varList[2] #index of complex used as the instance class arrayRepeater: def __init__(self,varList): self.offset = varList[0] #offset in array payload section self.repetitions = varList[1] #number of array repetitions self.complexIndex = varList[2] #not necessary for extraction def read(filename): global f1, f2, externalGUIDList, internalGUIDList, fields, complexes, header, trueFilename, arrayRepeaters, isPrimaryInstance, keywordDict #check magic try: f1=open(filename,"rb") except: return if f1.read(4)!="\xCE\xD1\xB2\x0F": f1.close() return print filename header=Header(unpack("11I",f1.read(44))) trueFilename="" #the cas extractor only guesses a filename which may be incorrect; but I do know how to find out the correct one #grab the file GUID and its primary instance. Make the hex numbers to string, e.g. 0x4b => "4b" fileGUID, primaryInstanceGUID = hexlify(f1.read(16)), hexlify(f1.read(16)) #add all GUID pairs to a list. These are external GUIDs so the first GUID is the GUID #of another file and the second belongs to an instance inside that file (may or may not be primary) externalGUIDList=[(hexlify(f1.read(16)),hexlify(f1.read(16))) for i in range(header.numGUID)] #make list of names and make a dictionary hash vs name keywords=str.split(f1.read(header.lenName),"\x00") ## while len(keywords[-1])==0: ## keywords.pop() #remove the last few empty entries which appeared due to null-padding; not necessary because keywordDict does not mind keywordDict=dict((hasher(keyword),keyword) for keyword in keywords) #read all fields and complexes into lists; replace hashes with names instantly fields=[FieldDescriptor(unpack("IHHII",f1.read(16))) for i in xrange(header.numField)] complexes=[ComplexDescriptor(unpack("IIBBHHH",f1.read(16))) for i in xrange(header.numComplex)] #read instanceRepeater and arrayRepeater, each entry consists of 3 unsigned ints instanceRepeaters=[instanceRepeater(unpack("3I",f1.read(12))) for i in range(header.numInstanceRepeater)] while f1.tell()%16!=0: f1.seek(1,1) #padding arrayRepeaters=[arrayRepeater(unpack("3I",f1.read(12))) for i in range(header.numArrayRepeater)] #ignore string section and read directly only when necessary. The elements are accessed directly via offset instead of index. f1.seek(header.absStringOffset+header.lenString) #START OF PAYLOAD SECTION ##make a list of all internal instance GUID, ignore the actual payload; this way I can instantly replace a payload Guid index with a string internalGUIDList=[] for instanceRepeater in instanceRepeaters: for repetition in xrange(instanceRepeater.repetitions): internalGUIDList.append(hexlify(f1.read(16))) f1.seek(complexes[instanceRepeater.complexIndex].size,1) f1.seek(header.absStringOffset+header.lenString) # go back to start of payload section ##do the same as above, but 1) don't make a list and 2) read the payload f2=StringIO() #prepare stream to write the output into memory because filename is not known yet for instanceRepeater in instanceRepeaters: instance=complexes[instanceRepeater.complexIndex] for repetition in xrange(instanceRepeater.repetitions): tabLevel=1 instanceGUID=hexlify(f1.read(16)) startPos=f1.tell() if instanceGUID==primaryInstanceGUID: f2.write(instance.name+" "+instanceGUID+" #primary instance\r\n") isPrimaryInstance=True else: f2.write(instance.name+" "+instanceGUID+"\r\n") isPrimaryInstance=False readComplex(instance,tabLevel) f1.seek(startPos+instance.size) f1.close() # the source file is read and everything is in the f2 stream #create folder, file, etc. try: outFilename=os.path.join(outputFolder,trueFilename)+" "+fileGUID+".txt" if not os.path.isdir(os.path.dirname(outFilename)): os.makedirs(os.path.dirname(outFilename)) f3=open(outFilename,"wb") f3.write(f2.getvalue()) f3.close() except: print "Could not write file "+filename try: f3.close() except: pass f2.close() ##field types sorted by the value of their ref: ##ref==0 ("7d40","0dc1","3dc1","4dc1","5dc1","adc0","bdc0","ddc0","edc0","fdc0","3500"): ## 7d40: 4bytes; string, the value is the offset in the string section ## 0dc1: 4bytes; uint32 ## 3dc1: 4bytes; single float ## 4dc1: 8bytes; double float ## 5dc1: 16bytes; GUID, referring to chunk files? ## adc0: 1byte; bool, padded to 4 if no other adc0,bdc0, the same applies to the other <4 bytes values ## bdc0: 1byte; int8 ## ddc0: 2bytes; uint16 ## edc0: 2bytes; int16 ## fdc0: 4bytes; int32 ## 3500: 4bytes; GUID index, read as uint32 and the first bit is the isExternal flag. Do >>31 and afterwards use it as the index for the right GUID table ## ## ##ref!=0 ("4100","2900","29d0"): ## 4100: 4bytes; arrayRepeater index ## 2900: 0bytes; complex entry ## 29d0: 0bytes; complex entry ## ## ##ref sometimes 0, sometimes non 0 ("0000","8900"): ## 0000: 0bytes when field within an enum or 8bytes (all nulls) when element of "$" (which indicates inheritance) ## 8900: 4bytes; enum. Find the enum corresponding to the payload value def readComplex(complex,tabLevel): #recursive function to read everything #get the fields for the complex fieldList=fields[complex.fieldStartIndex : complex.fieldStartIndex+complex.numField] startPos=f1.tell() if tabLevel!=1: f2.write("::"+complex.name+"\r\n") for field in fieldList: readField(field,startPos,tabLevel) f1.seek(startPos+complex.size) def readField(field,startPos,tabLevel): f1.seek(startPos+field.offset) ## f2.write("@"+str(f1.tell())) if field.type not in (0x0029,0xd029,0x0041,0x0000): #handle the simple stuff f2.write(tabLevel*"\t"+field.name+" "+unpackSimpleField(field)+"\r\n") elif field.type !=0x0041: #non arrays f2.write(tabLevel*"\t"+field.name) readComplex(complexes[field.ref],tabLevel+1) #recursion else: #arrays arrayIndex=unpack("I",f1.read(4))[0] if arrayIndex==0: #in contrast to the 0035 type, this time index 0 is reserved for these cases f2.write(tabLevel*"\t"+field.name+" *nullArray*"+"\r\n") return arrayRepeater=arrayRepeaters[arrayIndex] #no arrayIndex-1 necessary f1.seek(arrayRepeater.offset+header.absStringOffset+header.lenString+header.lenPayload) if arrayRepeater.repetitions==0: f2.write(tabLevel*"\t"+field.name+" *nullArray*"+"\r\n") else: arrayComplex=complexes[field.ref] memberField=fields[arrayComplex.fieldStartIndex] f2.write(tabLevel*"\t"+field.name) f2.write("::"+arrayComplex.name+"\r\n") for arrayRepetition in xrange(arrayRepeater.repetitions): position=f1.tell() readField(memberField,position,tabLevel+1) #recursion #make a dictionary for the number/bool types. Mainly to save me from bloating the function below too much. Single floats not included either because I want to display them properly. numDict={0xc10d:("I",4),0xc14d:("d",8),0xc0ad:("?",1),0xc0fd:("i",4),0xc0bd:("b",1),0xc0ed:("h",2), 0xc0dd:("H",2)} def unpackSimpleField(field): #read everything except 0x0029, 0xd029, 0x0041, 0x0000 #i.e. all assignments that do not contain another complex (0x0089 being the exception because it is so different) global trueFilename try: #if the entry is number/bool, extract it with the dictionary; else go to except (typ,length)=numDict[field.type] num=unpack(typ,f1.read(length))[0] return str(num) except: if field.type==0xc13d: return formatfloat(unpack("f",f1.read(4))[0]) if field.type==0xc15d: return hexlify(f1.read(16)) #GUID, neither external nor internal elif field.type==0xc0dd: return hexlify(f1.read(2)) #not sure about this type elif field.type==0x0089: if field.ref==0: return "*nullEnum*" else: #The field points at another complex. The fields in this complex then are the choices. #Basically I go through the fields one level deeper. These fields do not behave like actual fields, lots of nulls and offset is no offset at all. compareValue=unpack("I",f1.read(4))[0] #this value must match fakefield.offset fieldList=fields[complexes[field.ref].fieldStartIndex : complexes[field.ref].fieldStartIndex+complexes[field.ref].numField] for fakeField in fieldList: if fakeField.offset==compareValue: return fakeField.name elif field.type==0x407d: #the string section #The 4bytes payload are the offset, so we need to remember where we are, then jump and read #a null-terminated string and jump back originalPos=f1.tell() f1.seek(header.absStringOffset+unpack("I",f1.read(4))[0]) string="" while 1: a=f1.read(1) if a=="\x00": break else: string+=a f1.seek(originalPos+4) if len(string)==0: return "*nullString*" #actually the string is "" if isPrimaryInstance and trueFilename=="" and field.name=="Name": trueFilename=string return string elif field.type==0x0035: #Write the GUID of another instance. There are two different cases. #If the instance is found in another file use externalGUIDList (2*16 bytes). #If the instance is found in this file use internalGUIDList (1*16 bytes). #The first bit is the isExternal flag. => bitshift by 31 and bitmask GUIDIndex=unpack("I",f1.read(4))[0] if GUIDIndex>>31: return "-".join(externalGUIDList[GUIDIndex&0x7fffffff]) elif GUIDIndex==0: return "*nullGuid*" #this being handled differently by the engine is a bit annoying as internalGUIDList of course has an element at index 0 else: return internalGUIDList[GUIDIndex-1] #as a result, minus 1 is necessary def main(): if not outputFolder: return for ff in sys.argv[1:]: if os.path.isfile(ff): read(ff) else: for dir0,dirs,files in os.walk(ff): for f in files: read(dir0+"\\"+f) try: main() except Exception, e: raw_input(e) main() Edited January 29, 2013 by Frankelstner Quote Link to comment Share on other sites More sharing options...
rukqoa Posted November 16, 2011 Report Share Posted November 16, 2011 Amazing work! I've successfully extracted the files and I'm now trying to figure out how to make sense of the data. I get that fdc0 = integer, and adc0 = boolean, but how do I go from "8 10" to 100 (magazine capacity of M60)? Quote Link to comment Share on other sites More sharing options...
Frankelstner Posted November 16, 2011 Author Report Share Posted November 16, 2011 Amazing work! I've successfully extracted the files and I'm now trying to figure out how to make sense of the data. I get that fdc0 = integer, and adc0 = boolean, but how do I go from "8 10" to 100 (magazine capacity of M60)? You don't, at least not directly. The text file contains no values but merely tells us what to expect in the hex file. I'll try to explain the different parts of the text file. The number of assignments is hopefully explained well enough in the picture in my other post. Then you have a "04/10" line indicated by ------. You can still see the 04/10 in 043500 for example. The last value of a 04/10 specifies where this 04/10 ends (or the next one begins). Thus when looking at a larger section of several 04/10s (a section of the type which starts with ######) you can see the total length of that section by looking at this number at the last 04/10 in that section; i.e. the last value of the last 04/10 in a section gives the length of the section in the hex file. You MUST ignore the 16 byte hashes at the beginning however, all the offsets require you to start counting after a hash. The "00" lines are everything else. The 4 bytes seem to be the data type. The first number afterwards is the offset in the hex file. This offset is reset to null whenever a new section begins. As for the final number, I've made some guesses and was proven wrong again and again. I don't know its function yet. It's closely tied to the offset though. As for the thing you were looking for: http://imgur.com/CjrVi Note however that you can also find the magazine capacity at position 518 (in hex of course). It actually simply says "Ammo" at this very offset. Changing this value changes magazine capacity in SP. I suppose "Ammo" simply marks the beginning of a more detailed ammo section with lots of entries like this (this one appears much later on and in a different ##### section; I am not sure why): AmmoConfigData 042900 24 ---------- MagazineCapacity fdc00000 0 0 NumberOfMagazines fdc00000 4 4 TraceFrequency 0dc10000 8 8 AmmoPickupMinAmount 0dc10000 c c AmmoPickupMaxAmount 0dc10000 10 10 AutoReplenishMagazine adc00000 14 20 AutoReplenishDelay 3dc10000 18 14 AmmoBagPickupDelayMultiplier 3dc10000 1c 1c AmmoBagPickupAmount fdc00000 20 18 Conveniently MagazineCapacity is the first entry and thus appears immediately at the beginning of the "Ammo" section. It might be that the game simply knows what to expect when "Ammo" appears and reads the next xy bytes on its own. Quote Link to comment Share on other sites More sharing options...
rukqoa Posted November 16, 2011 Report Share Posted November 16, 2011 Ah.. Now I see that they're actually addresses. However, I still have trouble understanding the part of how you find the specific locations in the hex file based on the values in the text file. I mean, I understand that I can find the ammo count at position 518, but what I don't get is how you arrived at "518" based on the information in the file. Thanks for your time! Quote Link to comment Share on other sites More sharing options...
Frankelstner Posted November 16, 2011 Author Report Share Posted November 16, 2011 (edited) Ah.. Now I see that they're actually addresses. However, I still have trouble understanding the part of how you find the specific locations in the hex file based on the values in the text file. I mean, I understand that I can find the ammo count at position 518, but what I don't get is how you arrived at "518" based on the information in the file. Thanks for your time! Yup, it's quite difficult still. The issue is that some things seem to behave more or less randomly, otherwise I'd have put the text and hex part together already. Let's go through the weapon A91 d0a2a4d908882da38597a848e9eb46416abb710f (the weapons are very similar; the magazine capacity relative offset is the same for a large number of files, i.e. 0x46c). In the top there are path strings which I decided to include because they may or may not contain information necessary to understand the things below. You can ignore them for most purposes. Then there is a 16byte hash at 0x30 which belongs to the following section. For offset measurements you ignore this one too. Then you see some nulls, these can finally be found in the text file. Number of assignments of type below: 1 #################### ############################################################ DataContainer 043500 8 ---------- CameraRecoilData 043500 14 ---------- $ 00000000 0 0 SpringConstant 3dc10000 8 10 SpringDamping 3dc10000 c 14 SpringMinThresholdAngle 3dc10000 10 18 Hmm, the tabs are really horrible without notepad++. The first eight nulls after the hash belong to $ because $ starts at 0 and SpringConstant starts at 8 (one could argue with data types as well, maybe not so much when it just says $ 00000000). The bytes from 8 to c after the hash belong to SpringConstant, c to 10 SpringDamping. Finally SpringMinThresholdAngle goes from 10 to 14 because the 14 can be seen next to CameraRecoilData and thus defines the end of the section. The file then has another hash. Number of assignments of type below: 1 #################### ############################################################ EntityVoiceOverInfo 043500 28 ---------- $ 00000000 0 0 VoiceOverType 35000000 8 10 Labels 41000300 24 14 $ goes from 0 to 8, VoiceOverType goes from 8 to 24, Labels goes from 24 to 28. Number of assignments of type below: 2 #################### ############################################################ array 044100 4 ---------- member 35000000 0 0 GameDataContainer 043500 8 ---------- $ 00000000 0 0 FiringFunctionData 103500 560 ---------- $ 00000400 0 0 Dispersion 41000600 8 10 WeaponDispersion 29000800 c 14 FireEffects1p 41000900 50 58 FireEffects3p 41000900 54 5c Sound 35000000 58 60 Shot 29000c00 90 70 FireLogic 29000d00 3d0 d0 Ammo 29001600 46c 168 OverHeat 29001700 490 190 UsePrimaryAmmo adc00000 550 1f9 UnlimitedAmmoForAI adc00000 551 1f8 AmmoCrateReloadDelay 3dc10000 554 1f4 SelfHealTimeWhenDeployed 3dc10000 558 1f0 Another hash again. The following section then has 560 bytes (look at FiringFunctionData). After these 560 bytes there will be another hash and another section with 560bytes again (Number of assignments of type below: 2). Now in this file apparently "member" starts at 0, but so does $ of the two other ---- sections below (I have no explanation for that yet). Additionally the last thing, SelfHealTimeWhenDeployed, starts at 558 and is just another ordinary float. It should end at 55c, but the section has length 560. I could have saved all these ######## sections as separate files because getting to later parts in the file requires lots of manual work, though you can speed it up by finding things like 20 assignments of the same type to navigate faster. However I feel like they are connected somehow. You can see Ammo 29001600 46c 168 which apparently is an array defined later in the file. The first entry of Ammo happens to be MagazineCapacity. So you add 0x30 bytes for the path names. Then 0x10 for one hash and 0x14 for its entries. Then 0x10 for another hash and 0x28 for its entries. Then 0x10 for another hash and now the offsets can be used. It's tedious, but I can't do more until I understand these things better (which requires staring at these files unfortunately). If I were to make these offsets absolute for example I would need to calculate them for every single section, thus if a section has Number of assignments of type below: 5000 things will probably get out of hand. Two more things. There is another section (probably) unrelated after the hex stuff that has corresponding things in the text file. I'm not perfectly sure that it is unrelated though, so I included it. Also, it can be quite worthwhile to compare BC2 files with BF3 files, e.g. the materials file of a level in BC2 and a level in BF3: BC2: <instance guid="55E26A49-DB11-4435-9F83-3A5AA936F334" type="GameSharedResources.MaterialPropertySoundData"> <field name="SourceMaterial">GUIDnull</field> <field name="ImpactSound">GUIDnull</field> <field name="ScrapeSound">GUIDnull</field> <field name="ScrapeLength">1.0</field> <field name="SoldierSettings">GUIDa8ee7a57-dd90-4187-bdac-3f474799d307</field> <field name="Softness">0</field> </instance> BF3: MaterialPropertySoundData 043500 98 ---------- $ 00000a00 0 0 ImpactSound 35000000 8 18 ScrapeSound 35000000 3c 1c ScrapeLength 3dc10000 70 20 SoldierSettings 35000000 74 24 Softness 3dc10000 90 28 MaterialSoundId 3dc10000 94 2c So 35 seems to expect a GUID of some kind. Edited November 16, 2011 by Frankelstner Quote Link to comment Share on other sites More sharing options...
rukqoa Posted November 17, 2011 Report Share Posted November 17, 2011 Oh thanks! It makes some sense now. (Sort of) Well, I'm off to take a closer look and send the weapon stats to DenKirson so we can get a quick chart going. Interesting to note is that instead of having damage data inside the weapons files individually, they just defined the weapons' bullets and assigned dmg based on bullet caliber/type. Quote Link to comment Share on other sites More sharing options...
Frankelstner Posted November 17, 2011 Author Report Share Posted November 17, 2011 (edited) I slightly tweaked the start and end of ##### sections. Hopefully things are bundled together correctly now. At least the length of the entire section can be found right in the beginning instead of somewhere at the end. The entire arrangement makes more sense semantically too (which is how I figured this out; initially I bundled these things merely guided by hashes and got the name-hash function only later). Hmm... it's still incorrect. I'll need some time to meditate. Edited November 18, 2011 by Frankelstner Quote Link to comment Share on other sites More sharing options...
Frankelstner Posted November 18, 2011 Author Report Share Posted November 18, 2011 (edited) It seems to work correctly now. The next step is figuring out all the different assignment types. Once that is done everything can be put together. The first line now tells how it's called by other lines, e.g. "array 103500 560 -Referenced as: e". If another line has "FireEffects1p 4100 50 58 e array" then this line points at the first one. I've added "array" at the end of the second line for faster identification, but when there happen to be several arrays one still needs to look up the number. The number of whitespace on the left can be adjusted with the variable "padding" at the top of the code. Edited November 18, 2011 by Frankelstner Quote Link to comment Share on other sites More sharing options...
Frankelstner Posted November 20, 2011 Author Report Share Posted November 20, 2011 Done. This version does not read every assignment type yet (it should be simple enough to do that though). However it skips everything correctly and reads all floats, integers and bools I hope. Quote Link to comment Share on other sites More sharing options...
rukqoa Posted November 21, 2011 Report Share Posted November 21, 2011 THANK YOU! I've used the text convertor to extract some bullet data: http://www.bfeditor.org/forums/index.php?showtopic=15535 I will probably mess around a bit more and see if I can try to understand the explosive damage system (slightly different from BF2 or BC2) and the vehicles. Quote Link to comment Share on other sites More sharing options...
Frankelstner Posted November 21, 2011 Author Report Share Posted November 21, 2011 I will probably mess around a bit more and see if I can try to understand the explosive damage system (slightly different from BF2 or BC2) and the vehicles. The explosive system does not look different to me. One thing to keep in mind though, my cas extractor went for a relatively cheap way of figuring out the path structure (I've mentioned that in the thread too). It grabs the first path with two slashes in it. Thus the names are not always correct; so just go for relatively large files. I've discovered just yesterday where the correct paths are saved, might do it some time this week. First I'm going to take a break though. EmpTime 0.0 MaxOcclusionRaycastRadius 0.5 InnerBlastRadius 0.5 BlastDamage 112.0 BlastRadius 7.0 BlastImpulse 2000.0 HasStunEffect False ShockwaveDamage 1.0 ShockwaveRadius 10.0 ShockwaveImpulse 500.0 ShockwaveTime 0.25 DisableOcclusion False DisableStaticEntityOcclusion True CameraShockwaveRadius 0.0 SpawnDelay 0.0 TriggerImpairedHearing True DetonateOnce True <field name="EmpTime">0</field> <field name="CoreRadius">0.34</field> <field name="BlastDamage">100.0</field> <field name="InnerBlastRadius">0.34</field> <field name="BlastRadius">6.0</field> <field name="BlastImpulse">10000.0</field> <field name="ShockwaveDamage">1.0</field> <field name="ShockwaveRadius">10.0</field> <field name="ShockwaveImpulse">2000.0</field> <field name="ShockwaveTime">0.3</field> <field name="DisableOcclusion">false</field> <field name="DisableStaticEntityOcclusion">true</field> <field name="UseAsPreDestuctionEntity">false</field> <field name="UnspotsOnExplode">false</field> Quote Link to comment Share on other sites More sharing options...
rukqoa Posted November 21, 2011 Report Share Posted November 21, 2011 Yeah, but in some files, the same variables are defined twice, with different values. Not sure what's up with that... Quote Link to comment Share on other sites More sharing options...
mistan Posted November 21, 2011 Report Share Posted November 21, 2011 Yeah, but in some files, the same variables are defined twice, with different values. Not sure what's up with that... Hey rukqoa, If it's not too big of a hassle, could you explain how you were able to edit the initfs_win32 file and still be able to get online or even allow the game to start up in the 1st place. I've been trying tons of different things and combinations for the past few hours and I just cant figure it out. It either crashes bf3.exe before it's able to start properly or just hangs at "joining game" or "initializing". I want to up the graphics and animations in the game beyond the ULTRA settings and I would really appreciate it if you could help Quote Link to comment Share on other sites More sharing options...
rukqoa Posted November 22, 2011 Report Share Posted November 22, 2011 Hey rukqoa, If it's not too big of a hassle, could you explain how you were able to edit the initfs_win32 file and still be able to get online or even allow the game to start up in the 1st place. I've been trying tons of different things and combinations for the past few hours and I just cant figure it out. It either crashes bf3.exe before it's able to start properly or just hangs at "joining game" or "initializing". I want to up the graphics and animations in the game beyond the ULTRA settings and I would really appreciate it if you could help The end result has to be the exact same filesize as before you edit. Quote Link to comment Share on other sites More sharing options...
mistan Posted November 22, 2011 Report Share Posted November 22, 2011 The end result has to be the exact same filesize as before you edit. That's what I'm doing, it's exactly the same size. I havent been changing any true/false values. I've only been changing integer values. Even when changing one value from 0 to 1 causes the game to freeze. Would it be possible for you to change a few settings for me to test out and see? Quote Link to comment Share on other sites More sharing options...
rukqoa Posted November 22, 2011 Report Share Posted November 22, 2011 That's what I'm doing, it's exactly the same size. I havent been changing any true/false values. I've only been changing integer values. Even when changing one value from 0 to 1 causes the game to freeze. Would it be possible for you to change a few settings for me to test out and see? Did you encrypt it back? Quote Link to comment Share on other sites More sharing options...
mistan Posted November 22, 2011 Report Share Posted November 22, 2011 Did you encrypt it back? Yea, I used the method from here: http://www.bfeditor.org/forums/index.php?showtopic=15524 Quote Link to comment Share on other sites More sharing options...
Frankelstner Posted November 22, 2011 Author Report Share Posted November 22, 2011 I want to up the graphics and animations in the game beyond the ULTRA settings and I would really appreciate it if you could help Look, the first thing I'd do is to follow the steps rukqoa has given to turn off shadows to check that everything works correctly and that I understood the concept. Afterwards I'd try my own tweaks. It's not that hard really, just common sense! And if you did this and it crashed you can easily deduce that the game does simply does not accept the specific value you changed. Quote Link to comment Share on other sites More sharing options...
mistan Posted November 22, 2011 Report Share Posted November 22, 2011 (edited) Look, the first thing I'd do is to follow the steps rukqoa has given to turn off shadows to check that everything works correctly and that I understood the concept. Afterwards I'd try my own tweaks. It's not that hard really, just common sense! And if you did this and it crashed you can easily deduce that the game does simply does not accept the specific value you changed. I also tried that. I tried just turning off the shadows and nothing else. Maybe there are multiple ways to disable shadows. He didnt specifically say which cvar/command he changed. Sorry, I dont mean to be a bother. Edited November 22, 2011 by mistan Quote Link to comment Share on other sites More sharing options...
mistan Posted November 23, 2011 Report Share Posted November 23, 2011 Nevermind! I got it working!!! Wooo, time to take the graphics to a new level! Is it possible to get banned for this? Quote Link to comment Share on other sites More sharing options...
Frankelstner Posted November 23, 2011 Author Report Share Posted November 23, 2011 Nevermind! I got it working!!! Wooo, time to take the graphics to a new level! Is it possible to get banned for this? You'll most likely get kicked while joining if they decide to lock the file. It would be highly unusual if there were bans for this. Quote Link to comment Share on other sites More sharing options...
rukqoa Posted November 23, 2011 Report Share Posted November 23, 2011 You'll most likely get kicked while joining if they decide to lock the file. It would be highly unusual if there were bans for this. No kick, no ban. PB doesn't even bother to compare the hash. Quote Link to comment Share on other sites More sharing options...
Fox243 Posted December 2, 2011 Report Share Posted December 2, 2011 mistan can u explain what u were doing wrong im trying to mod the ps3 version and ur problem is kinda what im having the game freezes on boot and trial and error isnt is easy for me cuz every time i make a mod to the file i have to wait 9mins for the data transfer from one system to the other to test it the only thing im changing is the true to false and i take a . but it still craps out iv checked the size and its right so im starting to think the ps3 patch checks it self before boot if someone has advise it would be nice sincerely Fox Quote Link to comment Share on other sites More sharing options...
zoologist134 Posted December 2, 2011 Report Share Posted December 2, 2011 Try to use hex workshop to edit it. Quote Link to comment Share on other sites More sharing options...
Fox243 Posted December 2, 2011 Report Share Posted December 2, 2011 alright so i got the file to finally load but that file wont change anything for ps3 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.