toontown-just-works/toontown/estate/DistributedEstateAI.py
2024-07-07 18:08:39 -05:00

966 lines
No EOL
30 KiB
Python

from direct.directnotify import DirectNotifyGlobal
from direct.distributed.DistributedObjectAI import DistributedObjectAI
from toontown.toonbase import ToontownGlobals
import HouseGlobals
import time, random
from toontown.fishing.DistributedFishingPondAI import DistributedFishingPondAI
from toontown.fishing import FishingTargetGlobals, FishGlobals
from toontown.safezone import TreasureGlobals
from toontown.safezone.SZTreasurePlannerAI import SZTreasurePlannerAI
from toontown.safezone import DistributedEFlyingTreasureAI
from toontown.safezone import ButterflyGlobals
from toontown.safezone import DistributedButterflyAI
from toontown.safezone.DistributedFishingSpotAI import DistributedFishingSpotAI
from toontown.parties.DistributedPartyJukeboxActivityAI import DistributedPartyJukeboxActivityAI
from DistributedGardenBoxAI import *
from DistributedGardenPlotAI import *
from DistributedGagTreeAI import *
from DistributedFlowerAI import *
from DistributedStatuaryAI import *
from DistributedToonStatuaryAI import *
from DistributedAnimatedStatuaryAI import *
from DistributedChangingStatuaryAI import *
import GardenGlobals
from DistributedCannonAI import *
from DistributedTargetAI import *
import CannonGlobals
# planted, waterLevel, lastCheck, growthLevel, optional
NULL_PLANT = [-1, -1, 0, 0, 0]
NULL_TREES = [NULL_PLANT] * 8
NULL_FLOWERS = [NULL_PLANT] * 10
NULL_STATUARY = 0
NULL_DATA = {'trees': NULL_TREES, 'statuary': NULL_STATUARY, 'flowers': NULL_FLOWERS}
from direct.distributed.PyDatagramIterator import *
from direct.distributed.PyDatagram import *
class Garden:
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedEstateAI')
WANT_FLOWERS = True # puke
WANT_TREES = True
WANT_STATUARY = True
def __init__(self, air, avId):
self.air = air
self.avId = avId
self.trees = set()
self.flowers = set()
self.objects = set()
if not self.air.dbConn:
self.notify.warning('Not using mongodb, garden data will be non-persistent')
self.data = NULL_DATA.copy()
else:
d = self.air.dbGlobalCursor.gardens.find_one({'avId': avId})
if d is None:
self.data = NULL_DATA.copy()
self.air.dbGlobalCursor.gardens.update({'avId': avId}, {'$set': NULL_DATA}, upsert=True)
else:
self.data = d
self.data.pop('_id', None)
def destroy(self):
messenger.send('garden-%d-666-going-down' % self.avId)
for tree in self.trees:
tree.requestDelete()
for flower in self.flowers:
flower.requestDelete()
for object in self.objects:
object.requestDelete()
self.air = None
self.estateMgr = None
def create(self, estateMgr):
self.estateMgr = estateMgr
if self.avId not in estateMgr.toons:
estateMgr.notify.warning('Garden associated to unknown avatar %d, deleting...' % self.avId)
return False
houseIndex = estateMgr.toons.index(self.avId)
if self.WANT_FLOWERS:
boxIndex = 0
boxes = []
boxDefs = GardenGlobals.estateBoxes[houseIndex]
for x, y, h, boxType in boxDefs:
box = DistributedGardenBoxAI(self)
box.setTypeIndex(boxType)
box.setPos(x, y, 0)
box.setH(h)
box.setOwnerIndex(houseIndex)
box.generateWithRequired(estateMgr.zoneId)
self.objects.add(box)
boxes.append(box)
boxIndex += 1
self._boxes = boxes
plots = GardenGlobals.estatePlots[houseIndex]
treeIndex = 0
flowerIndex = 0
for plot, (x, y, h, type) in enumerate(plots):
if type == GardenGlobals.GAG_TREE_TYPE and self.WANT_TREES:
data = self.data['trees'][treeIndex]
planted, waterLevel, lastCheck, growthLevel, lastHarvested = data
if planted != -1:
obj = self.plantTree(treeIndex, planted, waterLevel=waterLevel,
lastCheck=lastCheck, growthLevel=growthLevel,
lastHarvested=lastHarvested, generate=False)
self.trees.add(obj)
else:
obj = self.placePlot(treeIndex)
obj.setPos(x, y, 0)
obj.setH(h)
obj.setPlot(plot)
obj.setOwnerIndex(houseIndex)
obj.generateWithRequired(estateMgr.zoneId)
treeIndex += 1
elif type == GardenGlobals.FLOWER_TYPE and self.WANT_FLOWERS:
data = self.data['flowers'][flowerIndex]
planted, waterLevel, lastCheck, growthLevel, variety = data
if planted != -1:
obj = self.plantFlower(flowerIndex, planted, variety, waterLevel=waterLevel,
lastCheck=lastCheck, growthLevel=growthLevel,
generate=False)
else:
obj = self.placePlot(flowerIndex)
obj.flowerIndex = flowerIndex
obj.setPlot(plot)
obj.setOwnerIndex(houseIndex)
obj.generateWithRequired(estateMgr.zoneId)
index = (0, 1, 2, 2, 2, 3, 3, 3, 4, 4)[flowerIndex]
idx = (0, 0, 0, 1, 2, 0, 1, 2, 0, 1)[flowerIndex]
obj.sendUpdate('setBoxDoId', [boxes[index].doId, idx])
flowerIndex += 1
elif type == GardenGlobals.STATUARY_TYPE and self.WANT_STATUARY:
data = self.data['statuary']
if data == 0:
obj = self.placePlot(-1)
else:
obj = self.placeStatuary(data, generate=False)
obj.setPos(x, y, 0)
obj.setH(h)
obj.setPlot(plot)
obj.setOwnerIndex(houseIndex)
obj.generateWithRequired(estateMgr.zoneId)
for tree in self.trees:
tree.calcDependencies()
self.reconsiderAvatarOrganicBonus()
return True
def hasTree(self, track, index):
x = track * 7 + index
for tree in self.data['trees']:
if tree[0] == x:
return True
return False
def getTree(self, track, index):
for tree in self.trees:
if tree.typeIndex == track * 7 + index:
return tree
def plantTree(self, treeIndex, value, plot=None, waterLevel=-1,
lastCheck=0, growthLevel=0, lastHarvested=0,
ownerIndex=-1, plotId=-1, pos=None, generate=True):
if not self.air:
return
if plot:
if plot not in self.objects:
return
plot.requestDelete()
self.objects.remove(plot)
tree = DistributedGagTreeAI(self)
tree.setTypeIndex(value)
tree.setWaterLevel(waterLevel)
tree.setGrowthLevel(growthLevel)
if ownerIndex != -1:
tree.setOwnerIndex(ownerIndex)
if plotId != -1:
tree.setPlot(plotId)
if pos is not None:
pos, h = pos
tree.setPos(pos)
tree.setH(h)
tree.treeIndex = treeIndex
tree.calculate(lastHarvested, lastCheck)
self.trees.add(tree)
if generate:
tree.generateWithRequired(self.estateMgr.zoneId)
return tree
def placePlot(self, treeIndex):
obj = DistributedGardenPlotAI(self)
obj.treeIndex = treeIndex
self.objects.add(obj)
return obj
def plantFlower(self, flowerIndex, species, variety, plot=None, waterLevel=-1,
lastCheck=0, growthLevel=0, ownerIndex=-1, plotId=-1, generate=True):
if not self.air:
return
if plot:
if plot not in self.objects:
return
plot.requestDelete()
self.objects.remove(plot)
flower = DistributedFlowerAI(self)
flower.setTypeIndex(species)
flower.setVariety(variety)
flower.setWaterLevel(waterLevel)
flower.setGrowthLevel(growthLevel)
if ownerIndex != -1:
flower.setOwnerIndex(ownerIndex)
if plotId != -1:
flower.setPlot(plotId)
flower.flowerIndex = flowerIndex
flower.calculate(lastCheck)
self.flowers.add(flower)
if generate:
flower.generateWithRequired(self.estateMgr.zoneId)
return flower
def placeStatuary(self, data, plot=None, plotId=-1, ownerIndex=-1,
pos=None, generate=True):
if not self.air:
return
if plot:
if plot not in self.objects:
return
plot.requestDelete()
self.objects.remove(plot)
data, lastCheck, index, growthLevel = self.S_unpack(data)
dclass = DistributedStatuaryAI
if index in GardenGlobals.ToonStatuaryTypeIndices:
dclass = DistributedToonStatuaryAI
elif index in GardenGlobals.ChangingStatuaryTypeIndices:
dclass = DistributedChangingStatuaryAI
elif index in GardenGlobals.AnimatedStatuaryTypeIndices:
dclass = DistributedAnimatedStatuaryAI
obj = dclass(self)
obj.growthLevel = growthLevel
obj.index = index
obj.data = data
if ownerIndex != -1:
obj.setOwnerIndex(ownerIndex)
if plotId != -1:
obj.setPlot(plotId)
if pos is not None:
pos, h = pos
obj.setPos(pos)
obj.setH(h)
obj.calculate(lastCheck)
self.objects.add(obj)
if generate:
obj.announceGenerate()
return obj
# Data structure
# VERY HIGH (vh) (64-bit)
# high high (H) = data (32-bit)
# high low (L) = lastCheck (32-bit)
# VERY LOW (vl) (16-bit)
# low high (h) = index (8-bit)
# low low (l) = growthLevel (8-bit)
@staticmethod
def S_pack(data, lastCheck, index, growthLevel):
vh = data << 32 | lastCheck
vl = index << 8 | growthLevel
return vh << 16 | vl
@staticmethod
def S_unpack(x):
vh = x >> 16
vl = x & 0xFFFF
data = vh >> 32
lastCheck = vh & 0xFFFFFFFF
index = vl >> 8
growthLevel = vl & 0xFF
return data, lastCheck, index, growthLevel
def getNullPlant(self):
return NULL_PLANT
def reconsiderAvatarOrganicBonus(self):
av = self.air.doId2do.get(self.avId)
if not av:
return
bonus = [-1] * 7
for track in xrange(7):
for level in xrange(8):#7
if not self.hasTree(track, level):
break
tree = self.getTree(track, level)
if tree.getGrowthLevel() < tree.growthThresholds[1] or tree.getWilted():
break
bonus[track] = level - 1
av.b_setTrackBonusLevel(bonus)
def update(self):
if self.air.dbConn:
self.air.dbGlobalCursor.gardens.update({'avId': self.avId}, {'$set': self.data}, upsert=True)
class GardenManager:
def __init__(self, mgr):
self.mgr = mgr
self.gardens = {}
def handleSingleGarden(self, avId):
g = Garden(self.mgr.air, avId)
g.gardenMgr = self
res = g.create(self.mgr)
if res:
self.gardens[avId] = g
def destroy(self):
for garden in self.gardens.values():
garden.destroy()
del self.gardens
class Rental:
def __init__(self, estate):
self.estate = estate
self.objects = set()
def destroy(self):
del self.estate
for object in self.objects:
if not object.isDeleted():
object.requestDelete()
taskMgr.remove(object.uniqueName('delete'))
self.objects = set()
class CannonRental(Rental):
def generateObjects(self):
target = DistributedTargetAI(self.estate.air)
target.generateWithRequired(self.estate.zoneId)
for drop in CannonGlobals.cannonDrops:
cannon = DistributedCannonAI(self.estate.air, self.estate.zoneId, target.doId, *drop)
cannon.generateWithRequired(self.estate.zoneId)
self.objects.add(cannon)
self.generateTreasures()
self.estate.b_setClouds(1)
def destroy(self):
self.estate.b_setClouds(0)
Rental.destroy(self)
def generateTreasures(self):
doIds = []
z = 35
for i in xrange(20):
x = random.randint(100, 300) - 200
y = random.randint(100, 300) - 200
treasure = DistributedEFlyingTreasureAI.DistributedEFlyingTreasureAI(self.estate.air, self, 7, x, y, z)
treasure.generateWithRequired(self.estate.zoneId)
self.objects.add(treasure)
doIds.append(treasure.doId)
self.estate.sendUpdate('setTreasureIds', [doIds])
def grabAttempt(self, avId, treasureId):
av = self.estate.air.doId2do.get(avId)
if av == None:
self.estate.air.writeServerEvent('suspicious', avId, 'TreasurePlannerAI.grabAttempt unknown avatar')
self.estate.notify.warning('avid: %s does not exist' % avId)
return
treasure = self.estate.air.doId2do.get(treasureId)
if self.validAvatar(av):
treasure.d_setGrab(avId)
self.deleteTreasureSoon(treasure)
else:
treasure.d_setReject()
def deleteTreasureSoon(self, treasure):
taskName = treasure.uniqueName('delete')
taskMgr.doMethodLater(5, self.__deleteTreasureNow, taskName, extraArgs=(treasure, taskName))
def __deleteTreasureNow(self, treasure, taskName):
treasure.requestDelete()
def validAvatar(self, av):
if av.getMaxHp() == av.getHp():
return 0
av.toonUp(3)
return 1
class DistributedEstateAI(DistributedObjectAI):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedEstateAI')
def __init__(self, air):
DistributedObjectAI.__init__(self, air)
self.toons = [0, 0, 0, 0, 0, 0]
self.items = [[], [], [], [], [], []]
self.estateType = 0
self.cloudType = 0
self.dawnTime = 0
self.lastEpochTimestamp = 0
self.rentalTimestamp = 0
self.houses = [None] * 6
self.rentalType = 0
self.rentalHandle = None
self.pond = None
self.jukebox = None
self.spots = []
self.butterflies = []
self.owner = None
self.gardenManager = GardenManager(self)
self.__pendingGardens = {}
@property
def hostId(self):
return 1000000001
def generate(self):
DistributedObjectAI.generate(self)
self.pond = DistributedFishingPondAI(simbase.air)
self.pond.setArea(ToontownGlobals.MyEstate)
self.pond.generateWithRequired(self.zoneId)
self.pond.start()
treasureType, healAmount, spawnPoints, spawnRate, maxTreasures = TreasureGlobals.SafeZoneTreasureSpawns[ToontownGlobals.MyEstate]
self.treasurePlanner = SZTreasurePlannerAI(self.zoneId, treasureType, healAmount, spawnPoints, spawnRate, maxTreasures)
self.treasurePlanner.start()
spot = DistributedFishingSpotAI(self.air)
spot.setPondDoId(self.pond.getDoId())
spot.setPosHpr(49.1029, -124.805, 0.344704, 90, 0, 0)
spot.generateWithRequired(self.zoneId)
self.spots.append(spot)
spot = DistributedFishingSpotAI(self.air)
spot.setPondDoId(self.pond.getDoId())
spot.setPosHpr(46.5222, -134.739, 0.390713, 75, 0, 0)
spot.generateWithRequired(self.zoneId)
self.spots.append(spot)
spot = DistributedFishingSpotAI(self.air)
spot.setPondDoId(self.pond.getDoId())
spot.setPosHpr(41.31, -144.559, 0.375978, 45, 0, 0)
spot.generateWithRequired(self.zoneId)
self.spots.append(spot)
spot = DistributedFishingSpotAI(self.air)
spot.setPondDoId(self.pond.getDoId())
spot.setPosHpr(46.8254, -113.682, 0.46015, 135, 0, 0)
spot.generateWithRequired(self.zoneId)
self.spots.append(spot)
self.jukebox = DistributedPartyJukeboxActivityAI(self.air, self.doId, (0, 0, 0, 0))
self.jukebox.generateWithRequired(self.zoneId)
self.jukebox.sendUpdate('setX', [-21.8630])
self.jukebox.sendUpdate('setY', [-154.669])
self.jukebox.sendUpdate('setH', [148.7050])
self.jukebox.sendUpdate('unloadSign')
ButterflyGlobals.generateIndexes(self.zoneId, ButterflyGlobals.ESTATE)
for i in xrange(0, ButterflyGlobals.NUM_BUTTERFLY_AREAS[ButterflyGlobals.ESTATE]):
for j in xrange(0, ButterflyGlobals.NUM_BUTTERFLIES[ButterflyGlobals.ESTATE]):
butterfly = DistributedButterflyAI.DistributedButterflyAI(self.air, ButterflyGlobals.ESTATE, i, self.zoneId)
butterfly.generateWithRequired(self.zoneId)
butterfly.start()
self.butterflies.append(butterfly)
def destroy(self):
for house in self.houses:
if house:
house.requestDelete()
for butterfly in self.butterflies:
if butterfly:
butterfly.requestDelete()
del self.houses[:]
if self.pond:
for spot in self.spots:
spot.requestDelete()
self.spots = []
self.pond.requestDelete()
self.pond = None
if self.jukebox:
self.jukebox.requestDelete()
if self.treasurePlanner:
self.treasurePlanner.stop()
self.gardenManager.destroy()
if self.rentalHandle:
self.rentalHandle.destroy()
self.rentalHandle = None
self.requestDelete()
def addDistObj(self, distObj):
self.doId2do[distObj.doId] = distObj
def setClientReady(self):
self.sendUpdate('setEstateReady', [])
def setEstateType(self, type):
self.estateType = type
def d_setEstateType(self, type):
self.sendUpdate('setEstateType', [type])
def b_setEstateType(self, type):
self.setEstateType(type)
self.d_setEstateType(type)
def getEstateType(self):
return self.estateType
def requestServerTime(self):
avId = self.air.getAvatarIdFromSender()
self.sendUpdateToAvatarId(avId, 'setServerTime', [time.time() % HouseGlobals.DAY_NIGHT_PERIOD])
def setDawnTime(self, dawnTime):
self.dawnTime = dawnTime
def d_setDawnTime(self, dawnTime):
self.sendUpdate('setDawnTime', [dawnTime])
def b_setDawnTime(self, dawnTime):
self.setDawnTime(dawnTime)
self.d_setDawnTime(dawnTime)
def getDawnTime(self):
return self.dawnTime
def setLastEpochTimeStamp(self, last):
self.lastEpochTimestamp = last
def d_setLastEpochTimeStamp(self, last):
self.sendUpdate('setLastEpochTimeStamp', [last])
def b_setLastEpochTimeStamp(self, last):
self.setLastEpochTimeStamp(last)
self.d_setLastEpochTimeStamp(last)
def getLastEpochTimeStamp(self):
return self.lastEpochTimestamp
def setRentalTimeStamp(self, rental):
self.rentalTimestamp = rental
def d_setRentalTimeStamp(self, rental):
self.sendUpdate('setRentalTimeStamp', [rental])
def b_setRentalTimeStamp(self, rental):
self.setRentalTimeStamp(rental)
self.d_setRentalTimeStamp(rental)
def getRentalTimeStamp(self):
return self.rentalTimestamp
def b_setRentalType(self, type):
self.d_setRentalType(type)
self.setRentalType(type)
def d_setRentalType(self, type):
self.sendUpdate('setRentalType', [type])
def setRentalType(self, type):
expirestamp = self.getRentalTimeStamp()
if expirestamp == 0:
expire = 0
else:
expire = int(expirestamp - time.time())
if expire < 0:
self.rentalType = 0
self.d_setRentalType(0)
self.b_setRentalTimeStamp(0)
else:
if self.rentalType == type:
return
self.rentalType = type
if self.rentalHandle:
self.rentalHandle.destroy()
self.rentalHandle = None
if self.rentalType == ToontownGlobals.RentalCannon:
self.rentalHandle = CannonRental(self)
else:
self.notify.warning('Unknown rental %s' % self.rentalType)
return
self.rentalHandle.generateObjects()
def getRentalType(self):
return self.rentalType
def rentItem(self, rentType, duration):
self.b_setRentalTimeStamp(time.time() + duration * 60)
self.b_setRentalType(rentType)
def setSlot0ToonId(self, id):
self.toons[0] = id
def d_setSlot0ToonId(self, id):
self.sendUpdate('setSlot0ToonId', [id])
def b_setSlot0ToonId(self, id):
self.setSlot0ToonId(id)
self.d_setSlot0ToonId(id)
def getSlot0ToonId(self):
return self.toons[0]
def setSlot0Items(self, items):
self.items[0] = items
def d_setSlot0Items(self, items):
self.sendUpdate('setSlot5Items', [items])
def b_setSlot0Items(self, items):
self.setSlot0Items(items)
self.d_setSlot0Items(items)
def getSlot0Items(self):
return self.items[0]
def setSlot1ToonId(self, id):
self.toons[1] = id
def d_setSlot1ToonId(self, id):
self.sendUpdate('setSlot1ToonId', [id])
def b_setSlot1ToonId(self, id):
self.setSlot1ToonId(id)
self.d_setSlot1ToonId(id)
def getSlot1ToonId(self):
return self.toons[1]
def setSlot1Items(self, items):
self.items[1] = items
def d_setSlot1Items(self, items):
self.sendUpdate('setSlot2Items', [items])
def b_setSlot1Items(self, items):
self.setSlot2Items(items)
self.d_setSlot2Items(items)
def getSlot1Items(self):
return self.items[1]
def setSlot2ToonId(self, id):
self.toons[2] = id
def d_setSlot2ToonId(self, id):
self.sendUpdate('setSlot2ToonId', [id])
def b_setSlot2ToonId(self, id):
self.setSlot2ToonId(id)
self.d_setSlot2ToonId(id)
def getSlot2ToonId(self):
return self.toons[2]
def setSlot2Items(self, items):
self.items[2] = items
def d_setSlot2Items(self, items):
self.sendUpdate('setSlot2Items', [items])
def b_setSlot2Items(self, items):
self.setSlot2Items(items)
self.d_setSlot2Items(items)
def getSlot2Items(self):
return self.items[2]
def setSlot3ToonId(self, id):
self.toons[3] = id
def d_setSlot3ToonId(self, id):
self.sendUpdate('setSlot3ToonId', [id])
def b_setSlot3ToonId(self, id):
self.setSlot3ToonId(id)
self.d_setSlot3ToonId(id)
def getSlot3ToonId(self):
return self.toons[3]
def setSlot3Items(self, items):
self.items[3] = items
def d_setSlot3Items(self, items):
self.sendUpdate('setSlot3Items', [items])
def b_setSlot3Items(self, items):
self.setSlot3Items(items)
self.d_setSlot3Items(items)
def getSlot3Items(self):
return self.items[3]
def setSlot4ToonId(self, id):
self.toons[4] = id
def d_setSlot4ToonId(self, id):
self.sendUpdate('setSlot4ToonId', [id])
def b_setSlot5ToonId(self, id):
self.setSlot4ToonId(id)
self.d_setSlot4ToonId(id)
def getSlot4ToonId(self):
return self.toons[4]
def setSlot4Items(self, items):
self.items[4] = items
def d_setSlot4Items(self, items):
self.sendUpdate('setSlot4Items', [items])
def b_setSlot4Items(self, items):
self.setSlot4Items(items)
self.d_setSlot4Items(items)
def getSlot4Items(self):
return self.items[4]
def setSlot5ToonId(self, id):
self.toons[5] = id
def d_setSlot5ToonId(self, id):
self.sendUpdate('setSlot5ToonId', [id])
def b_setSlot5ToonId(self, id):
self.setSlot5ToonId(id)
self.d_setSlot5ToonId(id)
def getSlot5ToonId(self):
return self.toons[5]
def setSlot5Items(self, items):
self.items[5] = items
def d_setSlot5Items(self, items):
self.sendUpdate('setSlot5Items', [items])
def b_setSlot5Items(self, items):
self.setSlot5Items(items)
self.d_setSlot5Items(items)
def getSlot5Items(self):
return self.items[5]
def setIdList(self, idList):
for i in xrange(len(idList)):
if i >= 6:
return
self.toons[i] = idList[i]
def d_setIdList(self, idList):
self.sendUpdate('setIdList', [idList])
def b_setIdList(self, idList):
self.setIdList(idList)
self.d_setIdLst(idList)
def completeFlowerSale(self, flag):
if not flag:
return
avId = self.air.getAvatarIdFromSender()
av = self.air.doId2do.get(avId)
if not av:
return
collection = av.flowerCollection
earning = 0
newSpecies = 0
for flower in av.flowerBasket.getFlower():
if collection.collectFlower(flower) == GardenGlobals.COLLECT_NEW_ENTRY:
newSpecies += 1
earning += flower.getValue()
av.b_setFlowerBasket([], [])
av.d_setFlowerCollection(*av.flowerCollection.getNetLists())
av.addMoney(earning)
oldSpecies = len(collection) - newSpecies
dt = abs(len(collection) // 10 - oldSpecies // 10)
if dt:
self.notify.info('%d is getting a gardening trophy!' % avId)
maxHp = av.getMaxHp()
maxHp = min(ToontownGlobals.MaxHpLimit, maxHp + dt)
av.b_setMaxHp(maxHp)
av.toonUp(maxHp)
self.sendUpdate('awardedTrophy', [avId])
av.b_setGardenTrophies(range(len(collection) // 10))
def completeFishSale(self):
avId = self.air.getAvatarIdFromSender()
av = self.air.doId2do.get(avId)
if not av:
return
if self.air.fishManager.creditFishTank(av):
self.sendUpdateToAvatarId(avId, 'thankSeller', [ToontownGlobals.FISHSALE_TROPHY, len(av.fishCollection), FishGlobals.getTotalNumFish()])
else:
self.sendUpdateToAvatarId(avId, 'thankSeller', [ToontownGlobals.FISHSALE_COMPLETE, 0, 0])
def setClouds(self, clouds):
self.cloudType = clouds
def d_setClouds(self, clouds):
self.sendUpdate('setClouds', [clouds])
def b_setClouds(self, clouds):
self.setClouds(clouds)
self.d_setClouds(clouds)
def getClouds(self):
return self.cloudType
# Garden methods
def getToonSlot(self, avId):
if avId not in self.toons:
return
return self.toons.index(avId)
def setSlot0Garden(self, flag):
self.__pendingGardens[0] = flag
def setSlot1Garden(self, flag):
self.__pendingGardens[1] = flag
def setSlot2Garden(self, flag):
self.__pendingGardens[2] = flag
def setSlot3Garden(self, flag):
self.__pendingGardens[3] = flag
def setSlot4Garden(self, flag):
self.__pendingGardens[4] = flag
def setSlot5Garden(self, flag):
self.__pendingGardens[5] = flag
def placeStarterGarden(self, avId, record=1):
av = self.air.doId2do.get(avId)
if not av:
return
slot = self.getToonSlot(avId)
if slot is None:
return
if record:
av.b_setGardenStarted(1)
self.sendUpdate('setSlot%dGarden' % slot, ['started'])
self.notify.info('placeStarterGarden %d %d' % (avId, slot))
self.gardenManager.handleSingleGarden(avId)
def announceGenerate(self):
DistributedObjectAI.announceGenerate(self)
self.sendUpdate('setIdList', [self.toons])
for index, started in self.__pendingGardens.items():
if started:
self.gardenManager.handleSingleGarden(self.toons[index])
self.__pendingGardens = {}
if config.GetBool('fake-garden-started-ai', False):
self.placeStarterGarden(100000002, 0)