from otp.ai.AIBaseGlobal import * import random, functools from toontown.suit import SuitDNA from direct.directnotify import DirectNotifyGlobal from toontown.suit import DistributedSuitAI from toontown.building import SuitBuildingGlobals class SuitPlannerInteriorAI: notify = DirectNotifyGlobal.directNotify.newCategory('SuitPlannerInteriorAI') def __init__(self, numFloors, bldgLevel, bldgTrack, zone, respectInvasions=1): self.dbg_nSuits1stRound = config.GetBool('n-suits-1st-round', 0) self.dbg_4SuitsPerFloor = config.GetBool('4-suits-per-floor', 0) self.dbg_1SuitPerFloor = config.GetBool('1-suit-per-floor', 0) self.zoneId = zone self.numFloors = numFloors self.respectInvasions = respectInvasions dbg_defaultSuitName = simbase.config.GetString('suit-type', 'random') if dbg_defaultSuitName == 'random': self.dbg_defaultSuitType = None else: self.dbg_defaultSuitType = SuitDNA.getSuitType(dbg_defaultSuitName) if isinstance(bldgLevel, str): self.notify.warning('bldgLevel is a string!') bldgLevel = int(bldgLevel) self._genSuitInfos(numFloors, bldgLevel, bldgTrack) return def __genJoinChances(self, num): joinChances = [] for currChance in range(num): joinChances.append(random.randint(1, 100)) joinChances.sort(key=functools.cmp_to_key(cmp)) return joinChances def _genSuitInfos(self, numFloors, bldgLevel, bldgTrack): self.suitInfos = [] self.notify.debug('\n\ngenerating suitsInfos with numFloors (' + str(numFloors) + ') bldgLevel (' + str(bldgLevel) + '+1) and bldgTrack (' + str(bldgTrack) + ')') for currFloor in range(numFloors): infoDict = {} lvls = self.__genLevelList(bldgLevel, currFloor, numFloors) activeDicts = [] maxActive = min(4, len(lvls)) if self.dbg_nSuits1stRound: numActive = min(self.dbg_nSuits1stRound, maxActive) else: numActive = random.randint(1, maxActive) if currFloor + 1 == numFloors and len(lvls) > 1: origBossSpot = len(lvls) - 1 if numActive == 1: newBossSpot = numActive - 1 else: newBossSpot = numActive - 2 tmp = lvls[newBossSpot] lvls[newBossSpot] = lvls[origBossSpot] lvls[origBossSpot] = tmp bldgInfo = SuitBuildingGlobals.SuitBuildingInfo[bldgLevel] if len(bldgInfo) > SuitBuildingGlobals.SUIT_BLDG_INFO_REVIVES: revives = bldgInfo[SuitBuildingGlobals.SUIT_BLDG_INFO_REVIVES][0] else: revives = 0 for currActive in range(numActive - 1, -1, -1): level = lvls[currActive] type = self.__genNormalSuitType(level) activeDict = {} activeDict['type'] = type activeDict['track'] = bldgTrack activeDict['level'] = level activeDict['revives'] = revives activeDicts.append(activeDict) infoDict['activeSuits'] = activeDicts reserveDicts = [] numReserve = len(lvls) - numActive joinChances = self.__genJoinChances(numReserve) for currReserve in range(numReserve): level = lvls[currReserve + numActive] type = self.__genNormalSuitType(level) reserveDict = {} reserveDict['type'] = type reserveDict['track'] = bldgTrack reserveDict['level'] = level reserveDict['revives'] = revives reserveDict['joinChance'] = joinChances[currReserve] reserveDicts.append(reserveDict) infoDict['reserveSuits'] = reserveDicts self.suitInfos.append(infoDict) def __genNormalSuitType(self, lvl): if self.dbg_defaultSuitType != None: return self.dbg_defaultSuitType return SuitDNA.getRandomSuitType(lvl) def __genLevelList(self, bldgLevel, currFloor, numFloors): bldgInfo = SuitBuildingGlobals.SuitBuildingInfo[bldgLevel] if self.dbg_1SuitPerFloor: return [1] else: if self.dbg_4SuitsPerFloor: return [5, 6, 7, 10] lvlPoolRange = bldgInfo[SuitBuildingGlobals.SUIT_BLDG_INFO_LVL_POOL] maxFloors = bldgInfo[SuitBuildingGlobals.SUIT_BLDG_INFO_FLOORS][1] lvlPoolMults = bldgInfo[SuitBuildingGlobals.SUIT_BLDG_INFO_LVL_POOL_MULTS] floorIdx = min(currFloor, maxFloors - 1) lvlPoolMin = lvlPoolRange[0] * lvlPoolMults[floorIdx] lvlPoolMax = lvlPoolRange[1] * lvlPoolMults[floorIdx] lvlPool = random.randint(int(lvlPoolMin), int(lvlPoolMax)) lvlMin = bldgInfo[SuitBuildingGlobals.SUIT_BLDG_INFO_SUIT_LVLS][0] lvlMax = bldgInfo[SuitBuildingGlobals.SUIT_BLDG_INFO_SUIT_LVLS][1] self.notify.debug('Level Pool: ' + str(lvlPool)) lvlList = [] while lvlPool >= lvlMin: newLvl = random.randint(lvlMin, min(lvlPool, lvlMax)) lvlList.append(newLvl) lvlPool -= newLvl if currFloor + 1 == numFloors: bossLvlRange = bldgInfo[SuitBuildingGlobals.SUIT_BLDG_INFO_BOSS_LVLS] newLvl = random.randint(bossLvlRange[0], bossLvlRange[1]) lvlList.append(newLvl) lvlList.sort(key=functools.cmp_to_key(cmp)) self.notify.debug('LevelList: ' + repr(lvlList)) return lvlList def __setupSuitInfo(self, suit, bldgTrack, suitLevel, suitType): suitName, skeleton = simbase.air.suitInvasionManager.getInvadingCog() if suitName and self.respectInvasions: suitType = SuitDNA.getSuitType(suitName) bldgTrack = SuitDNA.getSuitDept(suitName) suitLevel = min(max(suitLevel, suitType), suitType + 4) dna = SuitDNA.SuitDNA() dna.newSuitRandom(suitType, bldgTrack) suit.dna = dna self.notify.debug('Creating suit type ' + suit.dna.name + ' of level ' + str(suitLevel) + ' from type ' + str(suitType) + ' and track ' + str(bldgTrack)) suit.setLevel(suitLevel) return skeleton def __genSuitObject(self, suitZone, suitType, bldgTrack, suitLevel, revives=0): newSuit = DistributedSuitAI.DistributedSuitAI(simbase.air, None) skel = self.__setupSuitInfo(newSuit, bldgTrack, suitLevel, suitType) if skel: newSuit.setSkelecog(1) newSuit.setSkeleRevives(revives) newSuit.generateWithRequired(suitZone) newSuit.node().setName('suit-%s' % newSuit.doId) return newSuit def myPrint(self): self.notify.info('Generated suits for building: ') for currInfo in suitInfos: whichSuitInfo = suitInfos.index(currInfo) + 1 self.notify.debug(' Floor ' + str(whichSuitInfo) + ' has ' + str(len(currInfo[0])) + ' active suits.') for currActive in range(len(currInfo[0])): self.notify.debug(' Active suit ' + str(currActive + 1) + ' is of type ' + str(currInfo[0][currActive][0]) + ' and of track ' + str(currInfo[0][currActive][1]) + ' and of level ' + str(currInfo[0][currActive][2])) self.notify.debug(' Floor ' + str(whichSuitInfo) + ' has ' + str(len(currInfo[1])) + ' reserve suits.') for currReserve in range(len(currInfo[1])): self.notify.debug(' Reserve suit ' + str(currReserve + 1) + ' is of type ' + str(currInfo[1][currReserve][0]) + ' and of track ' + str(currInfo[1][currReserve][1]) + ' and of lvel ' + str(currInfo[1][currReserve][2]) + ' and has ' + str(currInfo[1][currReserve][3]) + '% join restriction.') def genFloorSuits(self, floor): suitHandles = {} floorInfo = self.suitInfos[floor] activeSuits = [] for activeSuitInfo in floorInfo['activeSuits']: suit = self.__genSuitObject(self.zoneId, activeSuitInfo['type'], activeSuitInfo['track'], activeSuitInfo['level'], activeSuitInfo['revives']) activeSuits.append(suit) suitHandles['activeSuits'] = activeSuits reserveSuits = [] for reserveSuitInfo in floorInfo['reserveSuits']: suit = self.__genSuitObject(self.zoneId, reserveSuitInfo['type'], reserveSuitInfo['track'], reserveSuitInfo['level'], reserveSuitInfo['revives']) reserveSuits.append((suit, reserveSuitInfo['joinChance'])) suitHandles['reserveSuits'] = reserveSuits return suitHandles def genSuits(self): suitHandles = [] for floor in range(len(self.suitInfos)): floorSuitHandles = self.genFloorSuits(floor) suitHandles.append(floorSuitHandles) return suitHandles