mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-23 03:35:12 -06:00
970 lines
44 KiB
Python
970 lines
44 KiB
Python
from direct.directnotify.DirectNotifyGlobal import *
|
|
from direct.distributed import DistributedObjectAI
|
|
from direct.task import Task
|
|
import random
|
|
|
|
import DistributedSuitAI
|
|
import SuitDNA
|
|
import SuitPlannerBase
|
|
import SuitTimings
|
|
from otp.ai.AIBaseGlobal import *
|
|
from toontown.battle import BattleManagerAI
|
|
from toontown.battle import SuitBattleGlobals
|
|
from toontown.building import HQBuildingAI
|
|
from toontown.building import SuitBuildingGlobals
|
|
from toontown.dna.DNAParser import DNASuitPoint
|
|
from toontown.hood import ZoneUtil
|
|
from toontown.suit.SuitInvasionGlobals import IFSkelecog, IFWaiter, IFV2
|
|
from libpandadna import *
|
|
from toontown.toon import NPCToons
|
|
from toontown.toonbase import ToontownBattleGlobals
|
|
from toontown.toonbase import ToontownGlobals
|
|
|
|
|
|
ALLOWED_FO_TRACKS = 's'
|
|
if config.GetBool('want-lawbot-cogdo', True):
|
|
ALLOWED_FO_TRACKS += 'l'
|
|
if config.GetBool('want-cashbot-cogdo', False):
|
|
ALLOWED_FO_TRACKS += 'c'
|
|
if config.GetBool('want-bossbot-cogdo', False):
|
|
ALLOWED_FO_TRACKS += 'b'
|
|
if config.GetBool('want-omni-cogdo', False):
|
|
ALLOWED_FO_TRACKS += 'slcb'
|
|
|
|
DEFAULT_COGDO_RATIO = .5
|
|
|
|
class DistributedSuitPlannerAI(DistributedObjectAI.DistributedObjectAI, SuitPlannerBase.SuitPlannerBase):
|
|
notify = directNotify.newCategory('DistributedSuitPlannerAI')
|
|
CogdoPopFactor = config.GetFloat('cogdo-pop-factor', 1.5)
|
|
CogdoRatio = min(1.0, max(0.0, config.GetFloat('cogdo-ratio', DEFAULT_COGDO_RATIO)))
|
|
MAX_SUIT_TYPES = 6
|
|
POP_UPKEEP_DELAY = 10
|
|
POP_ADJUST_DELAY = 300
|
|
PATH_COLLISION_BUFFER = 5
|
|
TOTAL_MAX_SUITS = 50
|
|
MIN_PATH_LEN = 40
|
|
MAX_PATH_LEN = 300
|
|
MIN_TAKEOVER_PATH_LEN = 2
|
|
SUITS_ENTER_BUILDINGS = 1
|
|
SUIT_BUILDING_NUM_SUITS = 1.5
|
|
SUIT_BUILDING_TIMEOUT = [
|
|
None, None, None, None, None, None,
|
|
72, 60, 48, 36, 24, 12, 6, 3, 1, 0.5
|
|
]
|
|
TOTAL_SUIT_BUILDING_PCT = 18 * CogdoPopFactor
|
|
BUILDING_HEIGHT_DISTRIBUTION = [14, 18, 25, 23, 20]
|
|
defaultSuitName = simbase.config.GetString('suit-type', 'random')
|
|
if defaultSuitName == 'random':
|
|
defaultSuitName = None
|
|
|
|
def __init__(self, air, zoneId):
|
|
DistributedObjectAI.DistributedObjectAI.__init__(self, air)
|
|
SuitPlannerBase.SuitPlannerBase.__init__(self)
|
|
self.air = air
|
|
self.zoneId = zoneId
|
|
self.canonicalZoneId = ZoneUtil.getCanonicalZoneId(zoneId)
|
|
if simbase.air.wantCogdominiums:
|
|
if not hasattr(self.__class__, 'CogdoPopAdjusted'):
|
|
self.__class__.CogdoPopAdjusted = True
|
|
for index in xrange(len(self.SuitHoodInfo)):
|
|
SuitBuildingGlobals.buildingMinMax[self.zoneId][0] = int(0.5 + self.CogdoPopFactor * SuitBuildingGlobals.buildingMinMax[self.zoneId][0])
|
|
SuitBuildingGlobals.buildingMinMax[self.zoneId][1] = int(0.5 + self.CogdoPopFactor * SuitBuildingGlobals.buildingMinMax[self.zoneId][1])
|
|
self.hoodInfoIdx = -1
|
|
for index in xrange(len(self.SuitHoodInfo)):
|
|
currHoodInfo = self.SuitHoodInfo[index]
|
|
if currHoodInfo[self.SUIT_HOOD_INFO_ZONE] == self.canonicalZoneId:
|
|
self.hoodInfoIdx = index
|
|
self.currDesired = None
|
|
self.baseNumSuits = (
|
|
self.SuitHoodInfo[self.hoodInfoIdx][self.SUIT_HOOD_INFO_MIN] +
|
|
self.SuitHoodInfo[self.hoodInfoIdx][self.SUIT_HOOD_INFO_MAX]) / 2
|
|
self.targetNumSuitBuildings = SuitBuildingGlobals.buildingMinMax[self.zoneId][0]
|
|
self.pendingBuildingTracks = []
|
|
self.pendingBuildingHeights = []
|
|
self.suitList = []
|
|
self.numFlyInSuits = 0
|
|
self.numBuildingSuits = 0
|
|
self.numAttemptingTakeover = 0
|
|
self.zoneInfo = {}
|
|
self.zoneIdToPointMap = None
|
|
self.cogHQDoors = []
|
|
self.battleList = []
|
|
self.battleMgr = BattleManagerAI.BattleManagerAI(self.air)
|
|
self.setupDNA()
|
|
if self.notify.getDebug():
|
|
self.notify.debug('Creating a building manager AI in zone' + str(self.zoneId))
|
|
self.buildingMgr = self.air.buildingManagers.get(self.zoneId)
|
|
if self.buildingMgr:
|
|
(blocks, hqBlocks, gagshopBlocks, petshopBlocks, kartshopBlocks) = self.buildingMgr.getDNABlockLists()
|
|
for currBlock in blocks:
|
|
bldg = self.buildingMgr.getBuilding(currBlock)
|
|
bldg.setSuitPlannerExt(self)
|
|
self.dnaStore.resetBlockNumbers()
|
|
self.initBuildingsAndPoints()
|
|
numSuits = simbase.config.GetInt('suit-count', -1)
|
|
if numSuits >= 0:
|
|
self.currDesired = numSuits
|
|
suitHood = simbase.config.GetInt('suits-only-in-hood', -1)
|
|
if suitHood >= 0:
|
|
if self.SuitHoodInfo[self.hoodInfoIdx][self.SUIT_HOOD_INFO_ZONE] != suitHood:
|
|
self.currDesired = 0
|
|
self.suitCountAdjust = 0
|
|
|
|
def cleanup(self):
|
|
taskMgr.remove(self.taskName('sptUpkeepPopulation'))
|
|
taskMgr.remove(self.taskName('sptAdjustPopulation'))
|
|
for suit in self.suitList:
|
|
suit.stopTasks()
|
|
if suit.isGenerated():
|
|
self.zoneChange(suit, suit.zoneId)
|
|
suit.requestDelete()
|
|
self.suitList = []
|
|
self.numFlyInSuits = 0
|
|
self.numBuildingSuits = 0
|
|
self.numAttemptingTakeover = 0
|
|
|
|
def delete(self):
|
|
self.cleanup()
|
|
DistributedObjectAI.DistributedObjectAI.delete(self)
|
|
SuitPlannerBase.SuitPlannerBase.delete(self)
|
|
|
|
def initBuildingsAndPoints(self):
|
|
if not self.buildingMgr:
|
|
return
|
|
if self.notify.getDebug():
|
|
self.notify.debug('Initializing building points')
|
|
self.buildingFrontDoors = {}
|
|
self.buildingSideDoors = {}
|
|
for p in self.frontdoorPointList:
|
|
blockNumber = p.getLandmarkBuildingIndex()
|
|
if blockNumber < 0:
|
|
self.notify.debug('No landmark building for (%s) in zone %s' % (str(p), self.zoneId))
|
|
continue
|
|
if blockNumber in self.buildingFrontDoors:
|
|
self.notify.debug('Multiple front doors for building %s in zone %s' % (blockNumber, self.zoneId))
|
|
continue
|
|
self.buildingFrontDoors[blockNumber] = p
|
|
for p in self.sidedoorPointList:
|
|
blockNumber = p.getLandmarkBuildingIndex()
|
|
if blockNumber < 0:
|
|
self.notify.debug('No landmark building for (%s) in zone %s' % (str(p), self.zoneId))
|
|
continue
|
|
if blockNumber in self.buildingSideDoors:
|
|
self.buildingSideDoors[blockNumber].append(p)
|
|
continue
|
|
self.buildingSideDoors[blockNumber] = [p]
|
|
for bldg in self.buildingMgr.getBuildings():
|
|
if isinstance(bldg, HQBuildingAI.HQBuildingAI):
|
|
continue
|
|
blockNumber = bldg.getBlock()[0]
|
|
if blockNumber not in self.buildingFrontDoors:
|
|
self.notify.debug('No front door for building %s in zone %s' % (blockNumber, self.zoneId))
|
|
if blockNumber not in self.buildingSideDoors:
|
|
self.notify.debug('No side door for building %s in zone %s' % (blockNumber, self.zoneId))
|
|
|
|
def countNumSuitsPerTrack(self, count):
|
|
for suit in self.suitList:
|
|
if suit.track in count:
|
|
count[suit.track] += 1
|
|
continue
|
|
count[suit.track] = 1
|
|
|
|
def countNumBuildingsPerTrack(self, count):
|
|
if not self.buildingMgr:
|
|
return
|
|
for building in self.buildingMgr.getBuildings():
|
|
if building.isSuitBuilding():
|
|
if building.track in count:
|
|
count[building.track] += 1
|
|
else:
|
|
count[building.track] = 1
|
|
|
|
def countNumBuildingsPerHeight(self, count):
|
|
if not self.buildingMgr:
|
|
return
|
|
for building in self.buildingMgr.getBuildings():
|
|
if building.isSuitBuilding():
|
|
height = building.numFloors - 1
|
|
if height in count:
|
|
count[height] += 1
|
|
else:
|
|
count[height] = 1
|
|
|
|
def formatNumSuitsPerTrack(self, count):
|
|
result = ' '
|
|
for (track, num) in count.items():
|
|
result += ' %s:%s' % (track, num)
|
|
return result[2:]
|
|
|
|
def calcDesiredNumFlyInSuits(self):
|
|
if self.currDesired is not None:
|
|
return 0
|
|
return self.baseNumSuits + self.suitCountAdjust
|
|
|
|
def calcDesiredNumBuildingSuits(self):
|
|
if self.currDesired is not None:
|
|
return self.currDesired
|
|
if not self.buildingMgr:
|
|
return 0
|
|
suitBuildings = self.buildingMgr.getEstablishedSuitBlocks()
|
|
return int(len(suitBuildings) * self.SUIT_BUILDING_NUM_SUITS)
|
|
|
|
def getZoneIdToPointMap(self):
|
|
if self.zoneIdToPointMap is not None:
|
|
return self.zoneIdToPointMap
|
|
self.zoneIdToPointMap = {}
|
|
for point in self.streetPointList:
|
|
points = self.dnaStore.getAdjacentPoints(point)
|
|
i = points.getNumPoints() - 1
|
|
while i >= 0:
|
|
pi = points.getPointIndex(i)
|
|
p = self.pointIndexes[pi]
|
|
i -= 1
|
|
zoneId = self.dnaStore.getSuitEdgeZone(point.getIndex(), p.getIndex())
|
|
if zoneId in self.zoneIdToPointMap:
|
|
self.zoneIdToPointMap[zoneId].append(point)
|
|
continue
|
|
self.zoneIdToPointMap[zoneId] = [point]
|
|
return self.zoneIdToPointMap
|
|
|
|
def getStreetPointsForBuilding(self, blockNumber):
|
|
pointList = []
|
|
if blockNumber in self.buildingSideDoors:
|
|
for doorPoint in self.buildingSideDoors[blockNumber]:
|
|
points = self.dnaStore.getAdjacentPoints(doorPoint)
|
|
i = points.getNumPoints() - 1
|
|
while i >= 0:
|
|
pi = points.getPointIndex(i)
|
|
point = self.pointIndexes[pi]
|
|
if point.getPointType() == DNASuitPoint.STREET_POINT:
|
|
pointList.append(point)
|
|
i -= 1
|
|
if blockNumber in self.buildingFrontDoors:
|
|
doorPoint = self.buildingFrontDoors[blockNumber]
|
|
points = self.dnaStore.getAdjacentPoints(doorPoint)
|
|
i = points.getNumPoints() - 1
|
|
while i >= 0:
|
|
pi = points.getPointIndex(i)
|
|
pointList.append(self.pointIndexes[pi])
|
|
i -= 1
|
|
return pointList
|
|
|
|
def createNewSuit(self, blockNumbers, streetPoints, toonBlockTakeover=None,
|
|
cogdoTakeover=None, minPathLen=None, maxPathLen=None,
|
|
buildingHeight=None, suitLevel=None, suitType=None, suitTrack=None,
|
|
suitName=None, skelecog=None, revives=None, waiter=None):
|
|
startPoint = None
|
|
blockNumber = None
|
|
if self.notify.getDebug():
|
|
self.notify.debug('Choosing origin from %d+%d possibles.' % (len(streetPoints), len(blockNumbers)))
|
|
while startPoint == None and len(blockNumbers) > 0:
|
|
bn = random.choice(blockNumbers)
|
|
blockNumbers.remove(bn)
|
|
if bn in self.buildingSideDoors:
|
|
for doorPoint in self.buildingSideDoors[bn]:
|
|
points = self.dnaStore.getAdjacentPoints(doorPoint)
|
|
i = points.getNumPoints() - 1
|
|
while blockNumber == None and i >= 0:
|
|
pi = points.getPointIndex(i)
|
|
p = self.pointIndexes[pi]
|
|
i -= 1
|
|
startTime = SuitTimings.fromSuitBuilding
|
|
startTime += self.dnaStore.getSuitEdgeTravelTime(doorPoint.getIndex(), pi, self.suitWalkSpeed)
|
|
if not self.pointCollision(p, doorPoint, startTime):
|
|
startTime = SuitTimings.fromSuitBuilding
|
|
startPoint = doorPoint
|
|
blockNumber = bn
|
|
while startPoint == None and len(streetPoints) > 0:
|
|
p = random.choice(streetPoints)
|
|
streetPoints.remove(p)
|
|
if not self.pointCollision(p, None, SuitTimings.fromSky):
|
|
startPoint = p
|
|
startTime = SuitTimings.fromSky
|
|
continue
|
|
if startPoint == None:
|
|
return None
|
|
newSuit = DistributedSuitAI.DistributedSuitAI(simbase.air, self)
|
|
newSuit.startPoint = startPoint
|
|
if blockNumber != None:
|
|
newSuit.buildingSuit = 1
|
|
if suitTrack == None:
|
|
suitTrack = self.buildingMgr.getBuildingTrack(blockNumber)
|
|
else:
|
|
newSuit.flyInSuit = 1
|
|
newSuit.attemptingTakeover = self.newSuitShouldAttemptTakeover()
|
|
if newSuit.attemptingTakeover:
|
|
if suitTrack == None and len(self.pendingBuildingTracks) > 0:
|
|
suitTrack = self.pendingBuildingTracks[0]
|
|
del self.pendingBuildingTracks[0]
|
|
self.pendingBuildingTracks.append(suitTrack)
|
|
|
|
if buildingHeight == None and len(self.pendingBuildingHeights) > 0:
|
|
buildingHeight = self.pendingBuildingHeights[0]
|
|
del self.pendingBuildingHeights[0]
|
|
self.pendingBuildingHeights.append(buildingHeight)
|
|
if suitName is None:
|
|
suitDeptIndex, suitTypeIndex, flags = self.air.suitInvasionManager.getInvadingCog()
|
|
if flags & IFSkelecog:
|
|
skelecog = 1
|
|
if flags & IFWaiter:
|
|
waiter = True
|
|
if flags & IFV2:
|
|
revives = 1
|
|
if suitDeptIndex is not None:
|
|
suitTrack = SuitDNA.suitDepts[suitDeptIndex]
|
|
if suitTypeIndex is not None:
|
|
suitName = self.air.suitInvasionManager.getSuitName()
|
|
else:
|
|
suitName = self.defaultSuitName
|
|
if (suitType is None) and (suitName is not None):
|
|
suitType = SuitDNA.getSuitType(suitName)
|
|
suitTrack = SuitDNA.getSuitDept(suitName)
|
|
if (suitLevel is None) and (buildingHeight is not None):
|
|
suitLevel = self.chooseSuitLevel(self.SuitHoodInfo[self.hoodInfoIdx][self.SUIT_HOOD_INFO_LVL], buildingHeight)
|
|
(suitLevel, suitType, suitTrack) = self.pickLevelTypeAndTrack(suitLevel, suitType, suitTrack)
|
|
newSuit.setupSuitDNA(suitLevel, suitType, suitTrack)
|
|
newSuit.buildingHeight = buildingHeight
|
|
gotDestination = self.chooseDestination(newSuit, startTime, toonBlockTakeover = toonBlockTakeover, cogdoTakeover = cogdoTakeover, minPathLen = minPathLen, maxPathLen = maxPathLen)
|
|
if not gotDestination:
|
|
self.notify.debug("Couldn't get a destination in %d!" % self.zoneId)
|
|
newSuit.doNotDeallocateChannel = None
|
|
newSuit.delete()
|
|
return None
|
|
newSuit.initializePath()
|
|
self.zoneChange(newSuit, None, newSuit.zoneId)
|
|
if skelecog:
|
|
newSuit.setSkelecog(skelecog)
|
|
newSuit.generateWithRequired(newSuit.zoneId)
|
|
if revives is not None:
|
|
newSuit.b_setSkeleRevives(revives)
|
|
if waiter:
|
|
newSuit.b_setWaiter(1)
|
|
newSuit.d_setSPDoId(self.doId)
|
|
newSuit.moveToNextLeg(None)
|
|
self.suitList.append(newSuit)
|
|
if newSuit.flyInSuit:
|
|
self.numFlyInSuits += 1
|
|
if newSuit.buildingSuit:
|
|
self.numBuildingSuits += 1
|
|
if newSuit.attemptingTakeover:
|
|
self.numAttemptingTakeover += 1
|
|
return newSuit
|
|
|
|
def countNumNeededBuildings(self):
|
|
if not self.buildingMgr:
|
|
return False
|
|
numSuitBuildings = len(self.buildingMgr.getSuitBlocks())
|
|
if (random.random() * 100) < SuitBuildingGlobals.buildingChance[self.zoneId]:
|
|
return SuitBuildingGlobals.buildingMinMax[self.zoneId][1] - numSuitBuildings
|
|
else:
|
|
return self.targetNumSuitBuildings - numSuitBuildings
|
|
|
|
def newSuitShouldAttemptTakeover(self):
|
|
if not self.SUITS_ENTER_BUILDINGS:
|
|
return False
|
|
numNeeded = self.countNumNeededBuildings()
|
|
if self.numAttemptingTakeover >= numNeeded:
|
|
self.pendingBuildingTracks = []
|
|
return False
|
|
self.notify.debug('DSP %s is planning a takeover attempt in zone %s' % (self.getDoId(), self.zoneId))
|
|
return True
|
|
|
|
def chooseDestination(self, suit, startTime, toonBlockTakeover=None,
|
|
cogdoTakeover=None, minPathLen=None, maxPathLen=None):
|
|
possibles = []
|
|
backup = []
|
|
|
|
if toonBlockTakeover is not None:
|
|
suit.attemptingTakeover = 1
|
|
blockNumber = toonBlockTakeover
|
|
if blockNumber in self.buildingFrontDoors:
|
|
possibles.append((blockNumber, self.buildingFrontDoors[blockNumber]))
|
|
elif suit.attemptingTakeover:
|
|
for blockNumber in self.buildingMgr.getToonBlocks():
|
|
building = self.buildingMgr.getBuilding(blockNumber)
|
|
(extZoneId, intZoneId) = building.getExteriorAndInteriorZoneId()
|
|
if not NPCToons.isZoneProtected(intZoneId):
|
|
if blockNumber in self.buildingFrontDoors:
|
|
possibles.append((blockNumber, self.buildingFrontDoors[blockNumber]))
|
|
if cogdoTakeover is None:
|
|
if suit.dna.dept in ALLOWED_FO_TRACKS:
|
|
cogdoTakeover = random.random() < self.CogdoRatio
|
|
elif self.buildingMgr:
|
|
for blockNumber in self.buildingMgr.getSuitBlocks():
|
|
track = self.buildingMgr.getBuildingTrack(blockNumber)
|
|
if (track == suit.track) and (blockNumber in self.buildingSideDoors):
|
|
for doorPoint in self.buildingSideDoors[blockNumber]:
|
|
possibles.append((blockNumber, doorPoint))
|
|
backup = []
|
|
for p in self.streetPointList:
|
|
backup.append((None, p))
|
|
if self.notify.getDebug():
|
|
self.notify.debug('Choosing destination point from %s+%s possibles.' % (len(possibles), len(backup)))
|
|
if len(possibles) == 0:
|
|
possibles = backup
|
|
backup = []
|
|
if minPathLen is None:
|
|
if suit.attemptingTakeover:
|
|
minPathLen = self.MIN_TAKEOVER_PATH_LEN
|
|
else:
|
|
minPathLen = self.MIN_PATH_LEN
|
|
if maxPathLen is None:
|
|
maxPathLen = self.MAX_PATH_LEN
|
|
retryCount = 0
|
|
while (len(possibles) > 0) and (retryCount < 50):
|
|
p = random.choice(possibles)
|
|
possibles.remove(p)
|
|
if len(possibles) == 0:
|
|
possibles = backup
|
|
backup = []
|
|
path = self.genPath(suit.startPoint, p[1], minPathLen, maxPathLen)
|
|
if path and (not self.pathCollision(path, startTime)):
|
|
suit.endPoint = p[1]
|
|
suit.minPathLen = minPathLen
|
|
suit.maxPathLen = maxPathLen
|
|
suit.buildingDestination = p[0]
|
|
suit.buildingDestinationIsCogdo = cogdoTakeover
|
|
suit.setPath(path)
|
|
return 1
|
|
retryCount += 1
|
|
return 0
|
|
|
|
def pathCollision(self, path, elapsedTime):
|
|
i = 0
|
|
pi = path.getPointIndex(i)
|
|
point = self.pointIndexes[pi]
|
|
adjacentPoint = self.pointIndexes[path.getPointIndex(i + 1)]
|
|
while (point.getPointType() == DNASuitPoint.FRONT_DOOR_POINT) or (
|
|
point.getPointType() == DNASuitPoint.SIDE_DOOR_POINT):
|
|
i += 1
|
|
lastPi = pi
|
|
pi = path.getPointIndex(i)
|
|
adjacentPoint = point
|
|
point = self.pointIndexes[pi]
|
|
elapsedTime += self.dnaStore.getSuitEdgeTravelTime(lastPi, pi, self.suitWalkSpeed)
|
|
result = self.pointCollision(point, adjacentPoint, elapsedTime)
|
|
return result
|
|
|
|
def pointCollision(self, point, adjacentPoint, elapsedTime):
|
|
for suit in self.suitList:
|
|
if suit.pointInMyPath(point, elapsedTime):
|
|
return 1
|
|
if adjacentPoint is not None:
|
|
return self.battleCollision(point, adjacentPoint)
|
|
else:
|
|
points = self.dnaStore.getAdjacentPoints(point)
|
|
i = points.getNumPoints() - 1
|
|
while i >= 0:
|
|
pi = points.getPointIndex(i)
|
|
p = self.pointIndexes[pi]
|
|
i -= 1
|
|
if self.battleCollision(point, p):
|
|
return 1
|
|
return 0
|
|
|
|
def battleCollision(self, point, adjacentPoint):
|
|
zoneId = self.dnaStore.getSuitEdgeZone(point.getIndex(), adjacentPoint.getIndex())
|
|
return self.battleMgr.cellHasBattle(zoneId)
|
|
|
|
def removeSuit(self, suit):
|
|
self.zoneChange(suit, suit.zoneId)
|
|
if self.suitList.count(suit) > 0:
|
|
self.suitList.remove(suit)
|
|
if suit.flyInSuit:
|
|
self.numFlyInSuits -= 1
|
|
if suit.buildingSuit:
|
|
self.numBuildingSuits -= 1
|
|
if suit.attemptingTakeover:
|
|
self.numAttemptingTakeover -= 1
|
|
suit.requestDelete()
|
|
|
|
def countTakeovers(self):
|
|
count = 0
|
|
for suit in self.suitList:
|
|
if suit.attemptingTakeover:
|
|
count += 1
|
|
return count
|
|
|
|
def __waitForNextUpkeep(self):
|
|
t = random.random() * 2.0 + self.POP_UPKEEP_DELAY
|
|
taskMgr.doMethodLater(t, self.upkeepSuitPopulation, self.taskName('sptUpkeepPopulation'))
|
|
|
|
def __waitForNextAdjust(self):
|
|
t = random.random() * 10.0 + self.POP_ADJUST_DELAY
|
|
taskMgr.doMethodLater(t, self.adjustSuitPopulation, self.taskName('sptAdjustPopulation'))
|
|
|
|
def upkeepSuitPopulation(self, task):
|
|
targetFlyInNum = self.calcDesiredNumFlyInSuits()
|
|
targetFlyInNum = min(targetFlyInNum, self.TOTAL_MAX_SUITS - self.numBuildingSuits)
|
|
streetPoints = self.streetPointList[:]
|
|
flyInDeficit = ((targetFlyInNum - self.numFlyInSuits) + 3) / 4
|
|
while flyInDeficit > 0:
|
|
if not self.createNewSuit([], streetPoints):
|
|
break
|
|
flyInDeficit -= 1
|
|
if self.buildingMgr:
|
|
suitBuildings = self.buildingMgr.getEstablishedSuitBlocks()
|
|
else:
|
|
suitBuildings = []
|
|
if self.currDesired != None:
|
|
targetBuildingNum = max(0, self.currDesired - self.numFlyInSuits)
|
|
else:
|
|
targetBuildingNum = int(len(suitBuildings) * self.SUIT_BUILDING_NUM_SUITS)
|
|
targetBuildingNum += flyInDeficit
|
|
targetBuildingNum = min(targetBuildingNum, self.TOTAL_MAX_SUITS - self.numFlyInSuits)
|
|
buildingDeficit = ((targetBuildingNum - self.numBuildingSuits) + 3) / 4
|
|
while buildingDeficit > 0:
|
|
if not self.createNewSuit(suitBuildings, streetPoints):
|
|
break
|
|
buildingDeficit -= 1
|
|
if self.notify.getDebug() and self.currDesired == None:
|
|
self.notify.debug('zone %d has %d of %d fly-in and %d of %d building suits.' % (self.zoneId, self.numFlyInSuits, targetFlyInNum, self.numBuildingSuits, targetBuildingNum))
|
|
if buildingDeficit != 0:
|
|
self.notify.debug('remaining deficit is %d.' % buildingDeficit)
|
|
if self.buildingMgr:
|
|
suitBuildings = self.buildingMgr.getEstablishedSuitBlocks()
|
|
timeoutIndex = min(len(suitBuildings), len(self.SUIT_BUILDING_TIMEOUT) - 1)
|
|
timeout = self.SUIT_BUILDING_TIMEOUT[timeoutIndex]
|
|
if timeout != None:
|
|
timeout *= 3600.0
|
|
oldest = None
|
|
oldestAge = 0
|
|
now = time.time()
|
|
for b in suitBuildings:
|
|
building = self.buildingMgr.getBuilding(b)
|
|
if hasattr(building, 'elevator'):
|
|
if building.elevator.fsm.getCurrentState().getName() == 'waitEmpty':
|
|
age = now - building.becameSuitTime
|
|
if age > oldestAge:
|
|
oldest = building
|
|
oldestAge = age
|
|
if oldestAge > timeout:
|
|
self.notify.info('Street %d has %d buildings; reclaiming %0.2f-hour-old building.' % (self.zoneId, len(suitBuildings), oldestAge / 3600.0))
|
|
oldest.b_setVictorList([0, 0, 0, 0])
|
|
oldest.updateSavedBy(None)
|
|
oldest.toonTakeOver()
|
|
self.__waitForNextUpkeep()
|
|
return Task.done
|
|
|
|
def adjustSuitPopulation(self, task):
|
|
hoodInfo = self.SuitHoodInfo[self.hoodInfoIdx]
|
|
if hoodInfo[self.SUIT_HOOD_INFO_MAX] == 0:
|
|
self.__waitForNextAdjust()
|
|
return Task.done
|
|
min = hoodInfo[self.SUIT_HOOD_INFO_MIN]
|
|
max = hoodInfo[self.SUIT_HOOD_INFO_MAX]
|
|
adjustment = random.choice((-2, -1, -1, 0, 0, 0, 1, 1, 2))
|
|
self.suitCountAdjust += adjustment
|
|
desiredNum = self.calcDesiredNumFlyInSuits()
|
|
if desiredNum < min:
|
|
self.suitCountAdjust = min - self.baseNumSuits
|
|
elif desiredNum > max:
|
|
self.suitCountAdjust = max - self.baseNumSuits
|
|
self.__waitForNextAdjust()
|
|
return Task.done
|
|
|
|
def suitTakeOver(self, blockNumber, suitTrack, difficulty, buildingHeight):
|
|
if self.pendingBuildingTracks.count(suitTrack) > 0:
|
|
self.pendingBuildingTracks.remove(suitTrack)
|
|
if self.pendingBuildingHeights.count(buildingHeight) > 0:
|
|
self.pendingBuildingHeights.remove(buildingHeight)
|
|
building = self.buildingMgr.getBuilding(blockNumber)
|
|
if building is None:
|
|
return
|
|
building.suitTakeOver(suitTrack, difficulty, buildingHeight)
|
|
|
|
def cogdoTakeOver(self, blockNumber, difficulty, buildingHeight, dept):
|
|
if self.pendingBuildingHeights.count(buildingHeight) > 0:
|
|
self.pendingBuildingHeights.remove(buildingHeight)
|
|
building = self.buildingMgr.getBuilding(blockNumber)
|
|
building.cogdoTakeOver(difficulty, buildingHeight, dept)
|
|
|
|
def recycleBuilding(self):
|
|
bmin = SuitBuildingGlobals.buildingMinMax[self.zoneId][0]
|
|
current = len(self.buildingMgr.getSuitBlocks())
|
|
if (self.targetNumSuitBuildings > bmin) and (current <= self.targetNumSuitBuildings):
|
|
self.targetNumSuitBuildings -= 1
|
|
self.assignSuitBuildings(1)
|
|
|
|
def createInitialSuitBuildings(self):
|
|
if self.buildingMgr is None:
|
|
return
|
|
|
|
# If we aren't at our minimum number of buildings, let's spawn some!
|
|
suitBlockCount = len(self.buildingMgr.getSuitBlocks())
|
|
if suitBlockCount < self.targetNumSuitBuildings:
|
|
for _ in xrange(self.targetNumSuitBuildings - suitBlockCount):
|
|
blockNumber = random.choice(self.buildingMgr.getToonBlocks())
|
|
building = self.buildingMgr.getBuilding(blockNumber)
|
|
if building is None:
|
|
continue
|
|
if NPCToons.isZoneProtected(building.getExteriorAndInteriorZoneId()[1]):
|
|
continue
|
|
suitName = self.air.suitInvasionManager.getInvadingCog()[0]
|
|
if suitName is None:
|
|
suitName = self.defaultSuitName
|
|
suitType = None
|
|
suitTrack = None
|
|
if suitName is not None:
|
|
suitType = SuitDNA.getSuitType(suitName)
|
|
suitTrack = SuitDNA.getSuitDept(suitName)
|
|
(suitLevel, suitType, suitTrack) = self.pickLevelTypeAndTrack(None, suitType, suitTrack)
|
|
building.suitTakeOver(suitTrack, suitLevel, None)
|
|
|
|
# Save the building manager's state:
|
|
self.buildingMgr.save()
|
|
|
|
def assignInitialSuitBuildings(self):
|
|
totalBuildings = 0
|
|
targetSuitBuildings = 0
|
|
actualSuitBuildings = 0
|
|
for sp in self.air.suitPlanners.values():
|
|
totalBuildings += len(sp.frontdoorPointList)
|
|
targetSuitBuildings += sp.targetNumSuitBuildings
|
|
if sp.buildingMgr:
|
|
actualSuitBuildings += len(sp.buildingMgr.getSuitBlocks())
|
|
wantedSuitBuildings = int((totalBuildings*self.TOTAL_SUIT_BUILDING_PCT) / 100)
|
|
self.notify.debug('Want %s out of %s total suit buildings; we currently have %s assigned, %s actual.' % (wantedSuitBuildings, totalBuildings, targetSuitBuildings, actualSuitBuildings))
|
|
if actualSuitBuildings > 0:
|
|
numReassigned = 0
|
|
for sp in self.air.suitPlanners.values():
|
|
if sp.buildingMgr:
|
|
numBuildings = len(sp.buildingMgr.getSuitBlocks())
|
|
else:
|
|
numBuildings = 0
|
|
if numBuildings > sp.targetNumSuitBuildings:
|
|
more = numBuildings - sp.targetNumSuitBuildings
|
|
sp.targetNumSuitBuildings += more
|
|
targetSuitBuildings += more
|
|
numReassigned += more
|
|
if numReassigned > 0:
|
|
self.notify.debug('Assigned %s buildings where suit buildings already existed.' % numReassigned)
|
|
if wantedSuitBuildings > targetSuitBuildings:
|
|
additionalBuildings = wantedSuitBuildings - targetSuitBuildings
|
|
self.assignSuitBuildings(additionalBuildings)
|
|
elif wantedSuitBuildings < targetSuitBuildings:
|
|
extraBuildings = targetSuitBuildings - wantedSuitBuildings
|
|
self.unassignSuitBuildings(extraBuildings)
|
|
|
|
def assignSuitBuildings(self, numToAssign):
|
|
hoodInfo = self.SuitHoodInfo[:]
|
|
totalWeight = self.TOTAL_BWEIGHT
|
|
totalWeightPerTrack = self.TOTAL_BWEIGHT_PER_TRACK[:]
|
|
totalWeightPerHeight = self.TOTAL_BWEIGHT_PER_HEIGHT[:]
|
|
numPerTrack = {
|
|
'c': 0,
|
|
'l': 0,
|
|
'm': 0,
|
|
's': 0
|
|
}
|
|
for sp in self.air.suitPlanners.values():
|
|
sp.countNumBuildingsPerTrack(numPerTrack)
|
|
numPerTrack['c'] += sp.pendingBuildingTracks.count('c')
|
|
numPerTrack['l'] += sp.pendingBuildingTracks.count('l')
|
|
numPerTrack['m'] += sp.pendingBuildingTracks.count('m')
|
|
numPerTrack['s'] += sp.pendingBuildingTracks.count('s')
|
|
numPerHeight = {
|
|
0: 0,
|
|
1: 0,
|
|
2: 0,
|
|
3: 0,
|
|
4: 0
|
|
}
|
|
for sp in self.air.suitPlanners.values():
|
|
sp.countNumBuildingsPerHeight(numPerHeight)
|
|
numPerHeight[0] += sp.pendingBuildingHeights.count(0)
|
|
numPerHeight[1] += sp.pendingBuildingHeights.count(1)
|
|
numPerHeight[2] += sp.pendingBuildingHeights.count(2)
|
|
numPerHeight[3] += sp.pendingBuildingHeights.count(3)
|
|
numPerHeight[4] += sp.pendingBuildingHeights.count(4)
|
|
while numToAssign > 0:
|
|
smallestCount = None
|
|
smallestTracks = []
|
|
for trackIndex in xrange(4):
|
|
if totalWeightPerTrack[trackIndex]:
|
|
track = SuitDNA.suitDepts[trackIndex]
|
|
count = numPerTrack[track]
|
|
if (smallestCount is None) or (count < smallestCount):
|
|
smallestTracks = [track]
|
|
smallestCount = count
|
|
elif count == smallestCount:
|
|
smallestTracks.append(track)
|
|
if not smallestTracks:
|
|
self.notify.info('No more room for buildings, with %s still to assign.' % numToAssign)
|
|
return
|
|
buildingTrack = random.choice(smallestTracks)
|
|
buildingTrackIndex = SuitDNA.suitDepts.index(buildingTrack)
|
|
smallestCount = None
|
|
smallestHeights = []
|
|
for height in xrange(5):
|
|
if totalWeightPerHeight[height]:
|
|
count = float(numPerHeight[height]) / float(self.BUILDING_HEIGHT_DISTRIBUTION[height])
|
|
if (smallestCount is None) or (count < smallestCount):
|
|
smallestHeights = [height]
|
|
smallestCount = count
|
|
elif count == smallestCount:
|
|
smallestHeights.append(height)
|
|
if not smallestHeights:
|
|
self.notify.info('No more room for buildings, with %s still to assign.' % numToAssign)
|
|
return
|
|
buildingHeight = random.choice(smallestHeights)
|
|
self.notify.info('Existing buildings are (%s, %s), choosing from (%s, %s), chose %s, %s.' % (self.formatNumSuitsPerTrack(numPerTrack), self.formatNumSuitsPerTrack(numPerHeight), smallestTracks, smallestHeights, buildingTrack, buildingHeight))
|
|
repeat = 1
|
|
while repeat and (buildingTrack is not None) and (buildingHeight is not None):
|
|
if len(hoodInfo) == 0:
|
|
self.notify.warning('No more streets can have suit buildings, with %s buildings unassigned!' % numToAssign)
|
|
return
|
|
repeat = 0
|
|
currHoodInfo = self.chooseStreetWithPreference(hoodInfo, buildingTrackIndex, buildingHeight)
|
|
zoneId = currHoodInfo[self.SUIT_HOOD_INFO_ZONE]
|
|
if zoneId in self.air.suitPlanners:
|
|
sp = self.air.suitPlanners[zoneId]
|
|
numTarget = sp.targetNumSuitBuildings
|
|
numTotalBuildings = len(sp.frontdoorPointList)
|
|
else:
|
|
numTarget = 0
|
|
numTotalBuildings = 0
|
|
if numTarget >= SuitBuildingGlobals.buildingMinMax[self.zoneId][1] or numTarget >= numTotalBuildings:
|
|
self.notify.info('Zone %s has enough buildings.' % zoneId)
|
|
hoodInfo.remove(currHoodInfo)
|
|
weight = currHoodInfo[self.SUIT_HOOD_INFO_BWEIGHT]
|
|
tracks = currHoodInfo[self.SUIT_HOOD_INFO_TRACK]
|
|
heights = currHoodInfo[self.SUIT_HOOD_INFO_HEIGHTS]
|
|
totalWeight -= weight
|
|
totalWeightPerTrack[0] -= weight * tracks[0]
|
|
totalWeightPerTrack[1] -= weight * tracks[1]
|
|
totalWeightPerTrack[2] -= weight * tracks[2]
|
|
totalWeightPerTrack[3] -= weight * tracks[3]
|
|
totalWeightPerHeight[0] -= weight * heights[0]
|
|
totalWeightPerHeight[1] -= weight * heights[1]
|
|
totalWeightPerHeight[2] -= weight * heights[2]
|
|
totalWeightPerHeight[3] -= weight * heights[3]
|
|
totalWeightPerHeight[4] -= weight * heights[4]
|
|
if totalWeightPerTrack[buildingTrackIndex] <= 0:
|
|
buildingTrack = None
|
|
if totalWeightPerHeight[buildingHeight] <= 0:
|
|
buildingHeight = None
|
|
repeat = 1
|
|
if (buildingTrack is not None) and (buildingHeight is not None):
|
|
sp.targetNumSuitBuildings += 1
|
|
sp.pendingBuildingTracks.append(buildingTrack)
|
|
sp.pendingBuildingHeights.append(buildingHeight)
|
|
self.notify.info('Assigning building to zone %s, pending tracks = %s, pending heights = %s' % (zoneId, sp.pendingBuildingTracks, sp.pendingBuildingHeights))
|
|
numPerTrack[buildingTrack] += 1
|
|
numPerHeight[buildingHeight] += 1
|
|
numToAssign -= 1
|
|
|
|
def unassignSuitBuildings(self, numToAssign):
|
|
hoodInfo = self.SuitHoodInfo[:]
|
|
totalWeight = self.TOTAL_BWEIGHT
|
|
while numToAssign > 0:
|
|
repeat = 1
|
|
while repeat:
|
|
if len(hoodInfo) == 0:
|
|
self.notify.warning('No more streets can remove suit buildings, with %s buildings too many!' % numToAssign)
|
|
return
|
|
repeat = 0
|
|
currHoodInfo = self.chooseStreetNoPreference(hoodInfo, totalWeight)
|
|
zoneId = currHoodInfo[self.SUIT_HOOD_INFO_ZONE]
|
|
if zoneId in self.air.suitPlanners:
|
|
sp = self.air.suitPlanners[zoneId]
|
|
numTarget = sp.targetNumSuitBuildings
|
|
numTotalBuildings = len(sp.frontdoorPointList)
|
|
else:
|
|
numTarget = 0
|
|
numTotalBuildings = 0
|
|
if numTarget <= SuitBuildingGlobals.buildingMinMax[self.zoneId][0]:
|
|
self.notify.info("Zone %s can't remove any more buildings." % zoneId)
|
|
hoodInfo.remove(currHoodInfo)
|
|
totalWeight -= currHoodInfo[self.SUIT_HOOD_INFO_BWEIGHT]
|
|
repeat = 1
|
|
self.notify.info('Unassigning building from zone %s.' % zoneId)
|
|
sp.targetNumSuitBuildings -= 1
|
|
numToAssign -= 1
|
|
|
|
def chooseStreetNoPreference(self, hoodInfo, totalWeight):
|
|
c = random.random() * totalWeight
|
|
t = 0
|
|
for currHoodInfo in hoodInfo:
|
|
weight = currHoodInfo[self.SUIT_HOOD_INFO_BWEIGHT]
|
|
t += weight
|
|
if c < t:
|
|
return currHoodInfo
|
|
self.notify.warning('Weighted random choice failed! Total is %s, chose %s' % (t, c))
|
|
return random.choice(hoodInfo)
|
|
|
|
def chooseStreetWithPreference(self, hoodInfo, buildingTrackIndex, buildingHeight):
|
|
dist = []
|
|
for currHoodInfo in hoodInfo:
|
|
weight = currHoodInfo[self.SUIT_HOOD_INFO_BWEIGHT]
|
|
thisValue = weight * currHoodInfo[self.SUIT_HOOD_INFO_TRACK][buildingTrackIndex] * currHoodInfo[self.SUIT_HOOD_INFO_HEIGHTS][buildingHeight]
|
|
dist.append(thisValue)
|
|
totalWeight = sum(dist)
|
|
c = random.random() * totalWeight
|
|
t = 0
|
|
for i in xrange(len(hoodInfo)):
|
|
t += dist[i]
|
|
if c < t:
|
|
return hoodInfo[i]
|
|
self.notify.warning('Weighted random choice failed! Total is %s, chose %s' % (t, c))
|
|
return random.choice(hoodInfo)
|
|
|
|
def chooseSuitLevel(self, possibleLevels, buildingHeight):
|
|
choices = []
|
|
for level in possibleLevels:
|
|
(minFloors, maxFloors) = SuitBuildingGlobals.SuitBuildingInfo[level - 1][0]
|
|
if buildingHeight >= minFloors - 1 and buildingHeight <= maxFloors - 1:
|
|
choices.append(level)
|
|
return random.choice(choices)
|
|
|
|
|
|
def initTasks(self):
|
|
if self.air.wantCogbuildings:
|
|
self.createInitialSuitBuildings()
|
|
self.__waitForNextUpkeep()
|
|
self.__waitForNextAdjust()
|
|
|
|
def resyncSuits(self):
|
|
for suit in self.suitList:
|
|
suit.resync()
|
|
|
|
def flySuits(self):
|
|
for suit in self.suitList:
|
|
if suit.pathState == 1:
|
|
suit.flyAwayNow()
|
|
|
|
def requestBattle(self, zoneId, suit, toonId):
|
|
self.notify.debug('requestBattle() - zone: %s suit: %s toon: %s' % (zoneId, suit.doId, toonId))
|
|
canonicalZoneId = ZoneUtil.getCanonicalZoneId(zoneId)
|
|
if canonicalZoneId not in self.battlePosDict:
|
|
return 0
|
|
toon = self.air.doId2do.get(toonId)
|
|
if toon.getBattleId() > 0:
|
|
self.notify.warning('We tried to request a battle when the toon was already in battle')
|
|
return 0
|
|
if toon:
|
|
if hasattr(toon, 'doId'):
|
|
toon.b_setBattleId(toonId)
|
|
|
|
pos = self.battlePosDict[canonicalZoneId]
|
|
|
|
interactivePropTrackBonus = -1
|
|
if config.GetBool('props-buff-battles', True) and canonicalZoneId in self.cellToGagBonusDict:
|
|
interactivePropTrackBonus = self.cellToGagBonusDict[canonicalZoneId]
|
|
|
|
self.battleMgr.newBattle(
|
|
zoneId, zoneId, pos, suit, toonId, self.__battleFinished,
|
|
self.SuitHoodInfo[self.hoodInfoIdx][self.SUIT_HOOD_INFO_SMAX],
|
|
interactivePropTrackBonus)
|
|
for currOther in self.zoneInfo[zoneId]:
|
|
self.notify.debug('Found suit %s in this new battle zone %s' % (currOther.getDoId(), zoneId))
|
|
if currOther != suit:
|
|
if currOther.pathState == 1 and currOther.legType == SuitLeg.TWalk:
|
|
self.checkForBattle(zoneId, currOther)
|
|
return 1
|
|
|
|
def __battleFinished(self, zoneId):
|
|
self.notify.debug('DistSuitPlannerAI: battle in zone ' + str(zoneId) + ' finished')
|
|
currBattleIdx = 0
|
|
while currBattleIdx < len(self.battleList):
|
|
currBattle = self.battleList[currBattleIdx]
|
|
if currBattle[0] == zoneId:
|
|
self.notify.debug('DistSuitPlannerAI: battle removed')
|
|
self.battleList.remove(currBattle)
|
|
currBattleIdx = currBattleIdx + 1
|
|
|
|
def __suitCanJoinBattle(self, zoneId):
|
|
battle = self.battleMgr.getBattle(zoneId)
|
|
if len(battle.suits) >= 4:
|
|
return 0
|
|
if battle:
|
|
if simbase.config.GetBool('suits-always-join', 0):
|
|
return 1
|
|
jChanceList = self.SuitHoodInfo[self.hoodInfoIdx][self.SUIT_HOOD_INFO_JCHANCE]
|
|
ratioIdx = (len(battle.toons) - battle.numSuitsEver) + 2
|
|
if ratioIdx >= 0:
|
|
if ratioIdx < len(jChanceList):
|
|
if random.randint(0, 99) < jChanceList[ratioIdx]:
|
|
return 1
|
|
else:
|
|
self.notify.warning('__suitCanJoinBattle idx out of range!')
|
|
return 1
|
|
return 0
|
|
|
|
|
|
def checkForBattle(self, zoneId, suit):
|
|
if self.battleMgr.cellHasBattle(zoneId):
|
|
if self.__suitCanJoinBattle(zoneId) and self.battleMgr.requestBattleAddSuit(zoneId, suit):
|
|
return 1
|
|
suit.flyAwayNow()
|
|
return 1
|
|
else:
|
|
return 0
|
|
|
|
|
|
def postBattleResumeCheck(self, suit):
|
|
self.notify.debug('DistSuitPlannerAI:postBattleResumeCheck: suit ' + str(suit.getDoId()) + ' is leaving battle')
|
|
battleIndex = 0
|
|
for currBattle in self.battleList:
|
|
if suit.zoneId == currBattle[0]:
|
|
self.notify.debug(' battle found' + str(suit.zoneId))
|
|
for currPath in currBattle[1]:
|
|
for currPathPtSuit in xrange(suit.currWpt, suit.myPath.getNumPoints()):
|
|
ptIdx = suit.myPath.getPointIndex(currPathPtSuit)
|
|
if self.notify.getDebug():
|
|
self.notify.debug(' comparing' + str(ptIdx) + 'with' + str(currPath))
|
|
if currPath == ptIdx:
|
|
if self.notify.getDebug():
|
|
self.notify.debug(' match found, telling' + 'suit to fly')
|
|
return 0
|
|
battleIndex += 1
|
|
pointList = []
|
|
for currPathPtSuit in xrange(suit.currWpt, suit.myPath.getNumPoints()):
|
|
ptIdx = suit.myPath.getPointIndex(currPathPtSuit)
|
|
if self.notify.getDebug():
|
|
self.notify.debug(' appending point with index of' + str(ptIdx))
|
|
pointList.append(ptIdx)
|
|
self.battleList.append([suit.zoneId, pointList])
|
|
return 1
|
|
|
|
def zoneChange(self, suit, oldZone, newZone=None):
|
|
if (oldZone in self.zoneInfo) and (suit in self.zoneInfo[oldZone]):
|
|
self.zoneInfo[oldZone].remove(suit)
|
|
if newZone is not None:
|
|
if newZone not in self.zoneInfo:
|
|
self.zoneInfo[newZone] = []
|
|
self.zoneInfo[newZone].append(suit)
|
|
|
|
def d_setZoneId(self, zoneId):
|
|
self.sendUpdate('setZoneId', [self.getZoneId()])
|
|
|
|
def getZoneId(self):
|
|
return self.zoneId
|
|
|
|
def suitListQuery(self):
|
|
suitIndexList = []
|
|
for suit in self.suitList:
|
|
suitIndexList.append(SuitDNA.suitHeadTypes.index(suit.dna.name))
|
|
self.sendUpdateToAvatarId(self.air.getAvatarIdFromSender(), 'suitListResponse', [suitIndexList])
|
|
|
|
def buildingListQuery(self):
|
|
buildingDict = {}
|
|
self.countNumBuildingsPerTrack(buildingDict)
|
|
buildingList = [0, 0, 0, 0]
|
|
for dept in SuitDNA.suitDepts:
|
|
if dept in buildingDict:
|
|
buildingList[SuitDNA.suitDepts.index(dept)] = buildingDict[dept]
|
|
self.sendUpdateToAvatarId(self.air.getAvatarIdFromSender(), 'buildingListResponse', [buildingList])
|
|
|
|
def pickLevelTypeAndTrack(self, level=None, type=None, track=None):
|
|
if level is None:
|
|
level = random.choice(self.SuitHoodInfo[self.hoodInfoIdx][self.SUIT_HOOD_INFO_LVL])
|
|
if type is None:
|
|
typeChoices = range(max(level - 4, 1), min(level, self.MAX_SUIT_TYPES) + 1)
|
|
type = random.choice(typeChoices)
|
|
else:
|
|
level = min(max(level, type), type + 4)
|
|
if track is None:
|
|
track = SuitDNA.suitDepts[SuitBattleGlobals.pickFromFreqList(self.SuitHoodInfo[self.hoodInfoIdx][self.SUIT_HOOD_INFO_TRACK])]
|
|
self.notify.debug('pickLevelTypeAndTrack: %s %s %s' % (level, type, track))
|
|
return (level, type, track)
|