def __createBossSkeleton(self, objType, objectData, parent, parentUid, objKey, dynamic, zoneId):
        skeleton = DistributedBossSkeletonAI(self.air)

        self.__setAvatarPosition(skeleton, objectData, parent, parentUid, objKey)
        skeleton.setScale(objectData.get('Scale'))
        skeleton.setUniqueId(objKey)


        avId = objectData.get('AvId', 1)
        avTrack = objectData.get('AvTrack', 0)
        avatarType = AvatarType(faction=AvatarTypes.Undead.faction, track=avTrack, id=avId)
        avatarType = avatarType.getBossType()
        skeleton.setAvatarType(avatarType)
        try:
            skeleton.loadBossData(objKey, avatarType)
        except:
            self.notify.warning('Failed to load %s (%s); An error occured while loading boss data' % (objType, objKey))
            return None

        skeleton.setName(skeleton.bossData['Name'])
        skeleton.setLevel(skeleton.bossData['Level'] or EnemyGlobals.getRandomEnemyLevel(avatarType))

        animSet = objectData.get('AnimSet', 'default')
        noticeAnim1 = objectData.get('Notice Animation 1', '')
        noticeAnim2 = objectData.get('Notice Animation 2', '')
        greetingAnim = objectData.get('Greeting Animation', '')
        skeleton.setActorAnims(animSet, noticeAnim1, noticeAnim2, greetingAnim)

        enemyHp, enemyMp = EnemyGlobals.getEnemyStats(avatarType, skeleton.getLevel())
        enemyHp = enemyHp * skeleton.bossData.get('HpScale', 1)
        enemyMp = enemyMp * skeleton.bossData.get('MpScale', 1)

        skeleton.setMaxHp(enemyHp)
        skeleton.setHp(skeleton.getMaxHp(), True)

        skeleton.setMaxMojo(enemyMp)
        skeleton.setMojo(enemyMp)

        weapons = EnemyGlobals.getEnemyWeapons(avatarType, skeleton.getLevel()).keys()
        skeleton.setCurrentWeapon(weapons[0], False)

        skeleton.setIsGhost(int(objectData.get('GhostFX', 0)))
        if 'GhostColor' in objectData and objectData['GhostColor'].isdigit():
            skeleton.setGhostColor(int(objectData.get('GhostColor', 0)))

        if 'Start State' in objectData:
            skeleton.setStartState(objectData['Start State'])

        self._enemies[objKey] = skeleton

        parent.generateChildWithRequired(skeleton, zoneId)
        skeleton.b_setVisZone(objectData.get('VisZone', ''))

        locationName = parent.getLocalizerName()
        self.notify.debug('Generating %s (%s) under zone %d in %s at %s with doId %d' % (skeleton.getName(), objKey, skeleton.zoneId, locationName, skeleton.getPos(), skeleton.doId))

        return skeleton
    def __createBossCreature(self, objType, objectData, parent, parentUid, objKey, dynamic, zoneId):
        creature = DistributedBossCreatureAI(self.air)

        self.__setAvatarPosition(creature, objectData, parent, parentUid, objKey)
        creature.setScale(objectData.get('Scale'))
        creature.setUniqueId(objKey)

        species = objectData.get('Species', '')
        if species not in AvatarTypes.NPC_SPAWNABLES:
            self.notify.warning('Failed to spawn %s (%s); Not a valid species.' % (species, objKey))

        avatarType = random.choice(AvatarTypes.NPC_SPAWNABLES[species])()
        avatarType = avatarType.getBossType()
        creature.setAvatarType(avatarType)
        try:
            creature.loadBossData(objKey, avatarType)
        except:
            self.notify.warning('Failed to load %s (%s); An error occured while loading boss data' % (objType, objKey))
            return None

        creature.setName(creature.bossData['Name'])
        creature.setLevel(creature.bossData['Level'] or EnemyGlobals.getRandomEnemyLevel(avatarType))

        animSet = objectData.get('AnimSet', 'default')
        noticeAnim1 = objectData.get('Notice Animation 1', '')
        noticeAnim2 = objectData.get('Notice Animation 2', '')
        greetingAnim = objectData.get('Greeting Animation', '')
        creature.setActorAnims(animSet, noticeAnim1, noticeAnim2, greetingAnim)

        enemyHp, enemyMp = EnemyGlobals.getEnemyStats(avatarType, creature.getLevel())
        enemyHp = enemyHp * creature.bossData.get('HpScale', 1)
        enemyMp = enemyMp * creature.bossData.get('MpScale', 1)

        creature.setMaxHp(enemyHp)
        creature.setHp(creature.getMaxHp(), True)

        creature.setMaxMojo(enemyMp)
        creature.setMojo(enemyMp)

        weapons = EnemyGlobals.getEnemyWeapons(avatarType, creature.getLevel()).keys()
        creature.setCurrentWeapon(weapons[0], False)

        if 'Start State' in objectData:
            creature.setStartState(objectData['Start State'])

        self._enemies[objKey] = creature

        parent.generateChildWithRequired(creature, zoneId)
        creature.b_setVisZone(objectData.get('VisZone', ''))

        locationName = parent.getLocalizerName()
        self.notify.debug('Generating %s (%s) under zone %d in %s at %s with doId %d' % (creature.getName(), objKey, creature.zoneId, locationName, creature.getPos(), creature.doId))

        return creature
    def __createBossGhost(self, objType, objectData, parent, parentUid, objKey, dynamic, zoneId):
        ghost = DistributedBossGhostAI(self.air)

        self.__setAvatarPosition(ghost, objectData, parent, parentUid, objKey)
        ghost.setScale(objectData.get('Scale'))
        ghost.setUniqueId(objKey)

        avId = objectData.get('AvId', 1)
        avTrack = objectData.get('AvTrack', 0)
        factionName = objectData.get('NavyFaction', 'Navy')
        if not hasattr(AvatarTypes, factionName):
            self.notify.warning('Failed to generate %s (%s); %s is not a valid faction' % (objType, objKey, factionName))
            return
        faction = getattr(AvatarTypes, factionName, AvatarTypes.Ghost)

        avatarType = AvatarType(faction=faction.faction, track=avTrack, id=avId)
        avatarType = avatarType.getBossType()
        ghost.setAvatarType(avatarType)
        try:
            ghost.loadBossData(objKey, avatarType)
        except:
            self.notify.warning('Failed to load %s (%s); An error occured while loading boss data' % (objType, objKey))
            return None

        ghost.setName(ghost.bossData['Name'])
        ghost.setLevel(ghost.bossData['Level'] or EnemyGlobals.getRandomEnemyLevel(avatarType))

        animSet = objectData.get('AnimSet', 'default')
        noticeAnim1 = objectData.get('Notice Animation 1', '')
        noticeAnim2 = objectData.get('Notice Animation 2', '')
        greetingAnim = objectData.get('Greeting Animation', '')
        ghost.setActorAnims(animSet, noticeAnim1, noticeAnim2, greetingAnim)

        enemyHp, enemyMp = EnemyGlobals.getEnemyStats(avatarType, ghost.getLevel())
        enemyHp = enemyHp * ghost.bossData.get('HpScale', 1)
        enemyMp = enemyMp * ghost.bossData.get('MpScale', 1)

        ghost.setMaxHp(enemyHp)
        ghost.setHp(ghost.getMaxHp(), True)

        ghost.setMaxMojo(enemyMp)
        ghost.setMojo(enemyMp)

        weapons = EnemyGlobals.getEnemyWeapons(avatarType, ghost.getLevel()).keys()
        ghost.setCurrentWeapon(weapons[0], False)

        ghost.setIsGhost(2)

        dnaId = objectData.get('DNA', objKey)
        if dnaId:
            ghost.setDNAId(dnaId)

        if 'Start State' in objectData:
            ghost.setStartState(objectData['Start State'])

        self._enemies[objKey] = ghost

        parent.generateChildWithRequired(ghost, zoneId)
        ghost.b_setVisZone(objectData.get('VisZone', ''))
        ghost.b_setGhostColor(13)

        locationName = parent.getLocalizerName()
        self.notify.debug('Generating %s (%s) under zone %d in %s at %s with doId %d' % (ghost.getName(), objKey, ghost.zoneId, locationName, ghost.getPos(), ghost.doId))

        return ghost
    def __createEnemy(self, objType, objectData, parent, parentUid, objKey, dynamic, zoneId):
        
        spawnable = objectData.get('Spawnables', '')
        if spawnable not in AvatarTypes.NPC_SPAWNABLES:
            self.notify.warning('Failed to spawn %s (%s); Not a valid spawnable.' % (spawnable, objKey))

        avatarType = random.choice(AvatarTypes.NPC_SPAWNABLES[spawnable])()
        bossType = avatarType.getRandomBossType()

        if bossType and self.wantRandomBosses:
            if random.randint(1, 100) <= self.randomBossChance:
                if bossType not in self.randomBosses or self.ignoreDoubleRandom:
                    self.randomBosses.append(bossType)
                    avatarType = bossType
            elif config.GetBool('force-random-bosses', False):
                if bossType not in self.randomBosses or self.ignoreDoubleRandom:
                    self.randomBosses.append(bossType)
                    avatarType = bossType
        
        enemyCls = None
        if avatarType.isA(AvatarTypes.Undead):
            if avatarType.getBoss():
                enemyCls = DistributedBossSkeletonAI
            else:
                enemyCls = DistributedNPCSkeletonAI
        elif avatarType.isA(AvatarTypes.TradingCo) or avatarType.isA(AvatarTypes.Navy):
            if avatarType.getBoss():
                enemyCls = DistributedBossNavySailorAI
            else:
                enemyCls = DistributedNPCNavySailorAI
        elif avatarType.isA(AvatarTypes.LandCreature) or avatarType.isA(AvatarTypes.AirCreature):
            if avatarType.getBoss():
                enemyCls = DistributedBossCreatureAI
            else:
                enemyCls = DistributedCreatureAI
        elif avatarType.isA(AvatarTypes.RageGhost):
            enemyCls = DistributedKillerGhostAI
        elif avatarType.isA(AvatarTypes.Ghost):
            enemyCls = DistributedGhostAI
        else:
            self.notify.warning('Received unknown AvatarType: %s' % avatarType)
            return

        if enemyCls is None:
            self.notify.warning('No Enemy class defined for AvatarType: %s' % avatarType)
            return

        enemy = enemyCls(self.air)
        self.__setAvatarPosition(enemy, objectData, parent, parentUid, objKey)
        enemy.setScale(objectData.get('Scale'))

        if avatarType.getBoss():
            enemy.setUniqueId('')
        else:
            enemy.setUniqueId(objKey)

        enemy.setAvatarType(avatarType)

        if avatarType.getBoss() and hasattr(enemy, 'loadBossData'):
            enemy.loadBossData(enemy.getUniqueId(), avatarType)

        animSet = objectData.get('AnimSet', 'default')
        noticeAnim1 = objectData.get('Notice Animation 1', '')
        noticeAnim2 = objectData.get('Notice Animation 2', '')
        greetingAnim = objectData.get('Greeting Animation', '')
        enemy.setActorAnims(animSet, noticeAnim1, noticeAnim2, greetingAnim)

        enemy.setLevel(EnemyGlobals.getRandomEnemyLevel(avatarType))

        enemyHp, enemyMp = EnemyGlobals.getEnemyStats(avatarType, enemy.getLevel())

        if avatarType.getBoss() and hasattr(enemy, 'bossData'):
            enemyHp = enemyHp * enemy.bossData['HpScale']
            enemyMp = enemyMp * enemy.bossData['MpScale']

        enemy.setMaxHp(enemyHp)
        enemy.setHp(enemy.getMaxHp(), True)

        enemy.setMaxMojo(enemyMp)
        enemy.setMojo(enemyMp)

        weapons = EnemyGlobals.getEnemyWeapons(avatarType, enemy.getLevel()).keys()
        enemy.setCurrentWeapon(weapons[0], False)

        enemy.setIsGhost(int(objectData.get('GhostFX', 0)))
        if 'GhostColor' in objectData and objectData['GhostColor'].isdigit():
            enemy.setGhostColor(int(objectData.get('GhostColor', 0)))

        dnaId = objKey
        if dnaId and hasattr(enemy,'setDNAId'):
            enemy.setDNAId(dnaId)

        name = avatarType.getName()
        if dnaId and dnaId in NPCList.NPC_LIST:
            name = NPCList.NPC_LIST[dnaId][NPCList.setName]

        if avatarType.getBoss():
            name = PLocalizer.BossNames[avatarType.faction][avatarType.track][avatarType.id][0]
        enemy.setName(name)  

        if 'Start State' in objectData:
            enemy.setStartState(objectData['Start State'])

        self._enemies[objKey] = enemy

        parent.generateChildWithRequired(enemy, zoneId)
        enemy.b_setVisZone(objectData.get('VisZone', ''))

        locationName = parent.getLocalizerName()
        self.notify.debug('Generating %s (%s) under zone %d in %s at %s with doId %d' % (enemy.getName(), objKey, enemy.zoneId, locationName, enemy.getPos(), enemy.doId))

        if avatarType.getBoss():
            self.notify.debug('Spawning boss %s (%s) on %s!' % (enemy.getName(), objKey, locationName))

        return enemy