Can you recommend a good IDE for it?
#------------------------------------------------------------------------------class NpcSkeletonPatcher(Patcher): """Changes skeletons of all NPCs to SkeletonBeast.""" group = _('Tweakers') name = _('Beastifier') text = _("Changes skeletons of all NPCs to SkeletonBeast.") #--Config Phase ----------------------------------------------------------- #--Patch Phase ------------------------------------------------------------ def getReadClasses(self): """Returns load factory classes needed for reading.""" if not self.isActive: return tuple() return (MreNpc,) def getWriteClasses(self): """Returns load factory classes needed for writing.""" if not self.isActive: return tuple() return (MreNpc,) def scanModFile(self,modFile,progress): """Scans specified mod file to extract info. May add record to patch mod, but won't alter it.""" if not self.isActive: return patchBlock = self.patchFile.NPC_ recordsById = patchBlock.recordsById modFile.convertToLongFormIds(('NPC_',)) for record in modFile.NPC_.getActiveRecords: if record.formid not in recordsById and record.model.path != 'SkeletonBeast': patchBlock.setRecord(record.formid,record) def buildPatch(self,log,progress): """Edits patch file as desired. Will write to log.""" if not self.isActive: return count = {} keep = self.patchFile.getKeeper() for record in self.patchFile.NPC_.records: model = record.model if model.path != 'SkeletonBeast': model.path = 'SkeletonBeast' model.modb = None #?? model.modt = None #?? keep(record.formid) srcMod = record.formid[0] count[srcMod] = count.get(srcMod,0) + 1 #--Log log.setHeader('= '+self.__class__.name) log(_('* %d Skeletons Tweaked') % (sum(count.values()),)) for srcMod in sorted(count.keys()): log(' * %3d %s' % (count[srcMod],srcMod))
class MreNpc(MreActor): """NPC Record. Non-Player Character.""" classType = 'NPC_' #--Main flags _flags = Flags(0L,Flags.getNames( ( 0,'female'), ( 1,'essential'), ( 3,'respawn'), ( 4,'autoCalc'), ( 7,'pcLevelOffset'), ( 9,'noLowLevel'), (13,'noRumors'), (14,'summonable'), (15,'noPersuasion'), (20,'canCorpseCheck'),)) #--AI Service flags aiService = Flags(0L,Flags.getNames( (0,'weapons'), (1,'armor'), (2,'clothing'), (3,'books'), (4,'ingredients'), (7,'lights'), (8,'apparatus'), (10,'miscItems'), (11,'spells'), (12,'magicItems'), (13,'potions'), (14,'training'), (16,'recharge'), (17,'repair'),)) #--Mel NPC DATA class MelNpcData(MelStruct): """Convert npc stats into skills, health, attributes.""" def loadData(self,record,ins,type,size,readId): unpacked = list(ins.unpack('=21BH2s8B',size,readId)) recordSetAttr = record.__setattr__ recordSetAttr('skills',unpacked[:21]) recordSetAttr('health',unpacked[21]) recordSetAttr('unused1',unpacked[22]) recordSetAttr('attributes',unpacked[23:]) if self._debug: print unpacked[:21],unpacked[21],unpacked[23:] def dumpData(self,record,out): """Dumps data from record to outstream.""" recordGetAttr = record.__getattribute__ values = recordGetAttr('skills')+[recordGetAttr('health')]+[recordGetAttr('unused1')]+recordGetAttr('attributes') out.packSub(self.subType,'=21BH2s8B',*values) #--Mel Set melSet = MelSet( MelString('EDID','eid'), MelString('FULL','full'), MelModel(), MelStruct('ACBS','=I3Hh2H', (_flags,'flags',0L),'baseSpell','fatigue','barterGold', ('level',1),'calcMin','calcMax'), MelStructs('SNAM','=IB3s','factions', (FID,'faction',None),'rank',('unused1','ODB')), MelFid('INAM','deathItem'), MelFid('RNAM','race'), MelFids('SPLO','spells'), MelFid('SCRI','script'), MelStructs('CNTO','Ii','items',(FID,'item',None),('count',1)), MelStruct('AIDT','=4BIbB2s', ('aggression',5),('confidence',50),('energyLevel',50),('responsibility',50), (aiService,'services',0L),'trainSkill','trainLevel',('unused1',null2)), MelFids('PKID','aiPackages'), MelStrings('KFFZ','animations'), MelFid('CNAM','iclass'), MelNpcData('DATA','',('skills',[0]*21),'health',('unused2',null2),('attributes',[0]*8)), MelFid('HNAM','hair'), MelOptStruct('LNAM','f',('hairLength',None)), MelFid('ENAM','eye'), ####fid Array MelStruct('HCLR','3Bs','hairRed','hairBlue','hairGreen',('unused3',null1)), MelFid('ZNAM','combatStyle'), MelBase('FGGS','fggs_p'), ####FaceGen Geometry-Symmetric MelBase('FGGA','fgga_p'), ####FaceGen Geometry-Asymmetric MelBase('FGTS','fgts_p'), ####FaceGen Texture-Symmetric MelStruct('FNAM','H','fnam'), ####Byte Array ) __slots__ = MreActor.__slots__ + melSet.getSlotsUsed() def setRace(self,race): """Set additional race info.""" self.race = race #--Model if not self.model: self.model = self.getDefault('model') if race in (0x23fe9,0x223c7): self.model.modPath = r"Characters\_Male\SkeletonBeast.NIF" else: self.model.modPath = r"Characters\_Male\skeleton.nif" #--FNAM fnams = { 0x23fe9 : 0x3cdc ,#--Argonian 0x224fc : 0x1d48 ,#--Breton 0x191c1 : 0x5472 ,#--Dark Elf 0x19204 : 0x21e6 ,#--High Elf 0x00907 : 0x358e ,#--Imperial 0x22c37 : 0x5b54 ,#--Khajiit 0x224fd : 0x03b6 ,#--Nord 0x191c0 : 0x0974 ,#--Orc 0x00d43 : 0x61a9 ,#--Redguard 0x00019 : 0x4477 ,#--Vampire 0x223c8 : 0x4a2e ,#--Wood Elf } self.fnam = fnams.get(race,0x358e)
for record in self.patchFile.NPC_.records: race = record.race model = record.model if (model.modPath != 'Characters\_male\SkeletonBeast.nif' and model.modPath != 'Characters\_male\SkeletonBeast.NIF' ): if (race == 0x3cdc or race == 0x5b54 ): model.modPath = 'Characters\_male\SkeletonBeast.nif' model.modb_p = None #?? model.modt_p = None #?? elif record.model.modPath == 'Characters\_male\SkeletonBeast.nif': if race in (0x224fc,0x191c1,0x19204,0x00907,0x224fd,0x00d43,0x00019,0x223c8): model.modPath = 'Characters\_male\Skeleton.nif' model.modb_p = None #?? model.modt_p = None #??