Revision 12 as of 2011-02-05 22:33:38

Clear message

sAPPNAME="DragonAge Face Replacer" sVERSION = "2.08" # 0.10 : Very first version # 0.11 : Fixed a bug on file mismatch, added some infos, changing processus method # 0.12 : added a Tkinter UI for file selection, old method is still valuable set UITOOL to False to enable # 0.20 : Now able to exchange with different filesizes ( MOR is written at the end of the file ) # 0.21 : Able to import from mor file instead of savegame # 0.22 : 0.21 bugfix and eyecandy # 1.00 : Final version, now able to retrieve MOR files from ERF resources # 1.01 : Adding some tweaking for destination savegames ( name ), as XunAmarox suggested # 1.02 : Some bugfix and eyecandy (list scrollbar), added inventory size tweaking ( always suggested by XunAmarox ) # 1.03 : Fixed some errors appearing with 1.02 and the separation between tweak and exchange face # 1.04 : Added compatibilty with Awakening and some save formats # 1.10 : Now save the path of the source and destination file, fixed the non-acsii names and paths # 1.11 : Fix 1.10 problem when trying to launch with bad paths and weird name problems # 1.20 : Now handle characters and saves in one window. UI improvements. Fixes problem with non-ascii paths # 1.30 : Now you can edit the face : model parts & tints. Log is less verbose # 2.00 : 1.30 version with reworked UI and handling # 2.01 : Fixes major bug in 2.00 with autocheck for characters and resource files # 2.02 : Fixes 2.01 problems in exchange of features, add more clearer paths and a "reset face" button # 2.03 : Fixes a script encoding error to save path, name exchange problems, features missing # 2.04 : Allowing to see source features values, limit inventory size, reworked code to handle a CheckList, more reliable log # 2.05 : Last bugfix of 2.0x serie, now things are 100% OK # 2.06 : Fixes a write error on savegames that prevent faces to be updated in some cases. Now faces are only appended, not replaced. # Fixes also an error in getting the last modified face # 2.07 : Simple fix about name problem: now if the name found is greater than nMAX_NAME, name cannot be changed (errors) # sAUTO_SELECT savegame is auto selected in character folder (based on a suggestion by setiweb) # Tint 11 & 12 is now eyebrow texture (thanks to setiweb) # 2.08 : 2.07 bugfix and code rewriting. It seems that some features (tatooes, age map) are not into features list # Also, now edited files can be put in another folder, use nSAVE_METHOD to achieve this

# Python modules import struct,os import os.path as OP import struct import shutil # Tkinter modules from Tkinter import * # Tkinter main import tkMessageBox as TKMB # Message box import tkFileDialog as TKFD # File dialog import tkFont import Tix # Tkinter extension from Tix import CheckList # Checklist

# Log level (0: errors only, 1: with informations, 2: with program flow) nLOG_LEVEL=0 # Save method : Set to # -1 to replace save witout backup # 0 to replace with making a backup # 1 to create a new slot nSAVE_METHOD=1 # previous paths for inputs # Default ERF resource may be "C:\MyGames\Dragon Age\packages\core\data\face.erf" pLAST_CHR="" pLAST_DAS="" pLAST_MOR="" pLAST_ERF="" # set to the directory of the characters in "(My Documents)\Bioware\Dragon Age\Characters" pCHARACTERS_DIR="" # Maximum inventory size allowed nMAX_INVSIZE=100000 # Max name size (only for file reading) nMAX_NAME=32 # select this savegame rather than first alphabetical save sAUTO_SELECT="QuickSave_1"

# Do not modify these lines nREL_OFFSET_INVSIZE=168 sPYTHON_FILE="DAFaceReplacer%s.py"%sVERSION.replace(".","") aMOR_FEATURES_PARTS=["P_head","P_eyes","P_hair","P_beard","P_part5","P_lashes"] aMOR_FEATURES_TINTS=["T_skin","T_lips","T_eyes","T_hair","T_eyelids","T_blush",

# Lines commented are features wanting a color mask editing aMOR_EDIT=(("Hair model",aMOR_FEATURES_PARTS[2]),

sMOR_HEADER="GFF V4.0PC MORPV0.1"

if not OP.exists(pLAST_DAS): pLAST_DAS="" if not OP.exists(pLAST_MOR): pLAST_MOR="" if not OP.exists(pLAST_ERF): pLAST_ERF="" if not OP.exists(pCHARACTERS_DIR): pCHARACTERS_DIR=os.getcwd()

def ChangeSaveData(daspath,new_name,new_invsize,morface):

def ChangeFaceData(dasdata,mordata):

def GetName(daspath,log=True):

def SetName(dasdata,newname):

def GetInvSize(daspath,log=True):

def SetInvSize(dasdata,invsize):

def GetMORData(daspath):

class ERFFile():

class MORFile():

# print nodes

# print morp

# print self.MP

# print self.MT

# print p

# print s,start

# print t

# print s,start

class DAFR(Frame):


None\t-> *.das -Edit face features, name, and inventory size

*.das\t-> *.das *.mor\t-> *.das *.erf\t-> *.das -Change face & edit face features, name and inventory size

None\t-> *.mor -Modify face in a exchangeable *.mor face file

*.mor\t-> *.mor -Edit *.mor face with another

*.das\t-> *.mor *.erf\t-> *.mor -Extract & modify face in a exchangeable *.mor face file -Edit *.mor face with another mor in savegame or resource

- extract the face from *.das or *.erf - edit the *.mor file in the Toolset - use as source for your savegame

# self.fSF={}

# self.fSF[ff[1]]=Checkbutton(self.fS_face,text="%s (%s)"%(ff[0],self.SRC_MOR.GetString(ff[1])))

# # ERF editing - forget in 2.00, mean to add faces into an ERF package # self.fD_resource=Frame(self.f_dst) # self.fDR_label=Label(self.fD_resource,text="Add to Resource",width=20) # self.fDR_name=Frame(self.fD_resource) # self.fDRN_label=Label(self.fDR_name,text="Filename",width=6) # self.fDRN_eName=Entry(self.fDR_name,width=14)

# self.fFC_path.pack(fill=X)

# self.fF_chr.pack() # self.fFD_path.pack(fill=X)

# self.fF_das.pack() # self.fFM_path.pack(fill=X)

# self.fF_mor.pack() # self.fFR_path.pack(fill=X)

# self.fF_res.pack()

# self.fSF_info.grid(row=0,column=0,sticky=W) # self.fSF_bToggle.grid(row=0,column=1) # self.fSF_cMorph.grid(row=1,column=0,sticky=W)

# for col in range(2): # for row in range(9): # if col==0 and row==0: continue # else: # ff=aMOR_EDIT[9*col+row-1] # self.fSF[ff[1]].grid(row=row+1,column=col,sticky=W)

# self.fDR_label.pack() # self.fDRN_label.pack(side=LEFT) # self.fDRN_eName.pack(side=LEFT) # self.fDR_name.pack() # self.fD_resource.pack()

# self.fDRN_eName["textvariable"]=self.res_filename

# self.copy_mask=[BooleanVar()] # self.fSF_cMorph["variable"]=self.copy_mask[0] # for x in range (len(aMOR_EDIT)): # v=BooleanVar() # self.copy_mask.append(v) # self.fSF[aMOR_EDIT[x][1]]["variable"]=self.copy_mask[x+1] # self.copy_mask.append(BooleanVar()) # self.fS_cName["variable"]=self.copy_mask[len(aMOR_EDIT)+1]

# for ff in aMOR_EDIT: self.fSF[ff[1]].select()

# Source and destination loading

# self.fSF[ff[1]]["text"]="%s (%s)"%(ff[0],self.SRC_MOR.GetString(ff[1])) # self.fSF[ff[1]].select()

# Character selection

# Resource File selection

# Source Edition

# self.fSF[ff[1]].deselect()

# self.fSF[ff[1]].select()

# Destination face editing

# Saving process

def Log(text,write=True):

def Message(frame,msg="A message",msgtype="i",log=True):

def UpdateScript(src,dst,text):

def SetPathText(control,path,prefix="",length=35):

def TruncatePath(path,prefix,length=35):

def GetType(path):

def GetTypeName(path): return ("None","Savegame","Face","Resource")[GetType(path)] def GetTypeColor(path): return ("black","darkgreen","darkblue","darkred")[GetType(path)]

LOG=open("DAFR_%s.log"%sVERSION,"w") Log("0Starting DragonAge Face Replacer v%s"%sVERSION) Log("0 Code is (c) 2010 NewByPower. See licence information in the script.") Log("0 Homepage: http://www.dragonagenexus.com/downloads/file.php?id=428") Log("0 Use [?] button to see a short help. See the readme for more explanations.")

root=Tix.Tk() UI=DAFR(root) UI.mainloop() root.destroy()

# Updating script globals # load python script pyfile=open(sPYTHON_FILE,"rb") txt=pyfile.read() pyfile.close() # update code txt=UpdateScript(UI.src,UI.dst,txt).encode("utf8") # rewrite python script pyfile=open(sPYTHON_FILE,"wb") pyfile.write(txt) pyfile.close()

Log("0Ending DragonAge Face Replacer") LOG.close()

Unable to edit the page? See the FrontPage for instructions.