Current garden progress.

This commit is contained in:
Loudrob 2015-07-20 15:53:53 -04:00
parent c93fec2f19
commit 1236e38d62
28 changed files with 1569 additions and 1012 deletions

View file

@ -1209,46 +1209,41 @@ struct decorItem {
};
struct lawnItem {
int8 plot;
uint8 type;
uint8 species;
uint8 variety;
uint8 hardPoint;
int8 waterLevel;
int8 growthLevel;
uint16 optional;
uint64 plantedAt;
uint64 wateredAt;
};
dclass DistributedEstate : DistributedObject {
string DcObjectType db;
setEstateReady() broadcast;
setClientReady() airecv clsend;
setEstateType(uint8 type = 0) required broadcast db;
setClosestHouse(uint8) airecv clsend;
setTreasureIds(uint32[]) broadcast ram;
requestServerTime() airecv clsend;
setServerTime(uint32);
setDawnTime(uint32) required broadcast ram;
placeOnGround(uint32) broadcast ram;
setDecorData(lawnItem items[] = []) required airecv db;
setLastEpochTimeStamp(uint32 timestamp = 0) required airecv db;
setRentalTimeStamp(uint32 timestamp = 0) required airecv db;
setRentalType(uint8 type = 0) required airecv db;
setSlot0ToonId(uint32 toonId = 0) required airecv db;
setSlot0Items(lawnItem items[] = []) required broadcast ownrecv db;
setSlot0Garden(blob g) required airecv db;
setSlot1ToonId(uint32 toonId = 0) required airecv db;
setSlot1Items(lawnItem items[] = []) required broadcast ownrecv db;
setSlot1Garden(blob g) required airecv db;
setSlot2ToonId(uint32 toonId = 0) required airecv db;
setSlot2Items(lawnItem items[] = []) required broadcast ownrecv db;
setSlot2Garden(blob g) required airecv db;
setSlot3ToonId(uint32 toonId = 0) required airecv db;
setSlot3Items(lawnItem items[] = []) required broadcast ownrecv db;
setSlot3Garden(blob g) required airecv db;
setSlot4ToonId(uint32 toonId = 0) required airecv db;
setSlot4Items(lawnItem items[] = []) required broadcast ownrecv db;
setSlot4Garden(blob g) required airecv db;
setSlot5ToonId(uint32 toonId = 0) required airecv db;
setSlot5Items(lawnItem items[] = []) required broadcast ownrecv db;
setSlot5Garden(blob g) required airecv db;
setIdList(uint32 []) broadcast ram;
completeFlowerSale(uint8) airecv clsend;
completeFishSale(uint8) airecv clsend;
thankSeller(int8, int8, int8);
awardedTrophy(uint32) broadcast;
setClouds(uint8) required broadcast ram;
cannonsOver() broadcast;
@ -1283,8 +1278,7 @@ dclass DistributedHouseInterior : DistributedObject {
};
dclass DistributedGarden : DistributedObject {
sendNewProp(uint8, int16/10, int16/10, int16/10) broadcast;
setProps(uint8[]) airecv clsend;
sendNewProp(uint8 prop, int16/10 x, int16/10 y, int16/10 z) broadcast;
};
dclass DistributedParty : DistributedObject {
@ -2556,27 +2550,24 @@ dclass DistributedLawbotChair : DistributedObject {
};
dclass DistributedLawnDecor : DistributedNode {
setEstate(uint32) required broadcast ram;
setPlot(int8) required broadcast ram;
setHeading(int16/10) required broadcast ram;
setPosition(int16/10, int16/10, int16/10) required broadcast ram;
setOwnerIndex(int8) required broadcast ram;
setPosition(int16/10, int16/10, int16/10) required broadcast ram;
plotEntered() airecv clsend;
removeItem(uint32) airecv clsend;
removeItem() airecv clsend;
setMovie(uint8, uint32) broadcast ram;
movieDone() airecv clsend;
interactionDenied(uint32) broadcast ram;
setBoxDoId(uint32, uint8) broadcast ram;
};
dclass DistributedGardenPlot : DistributedLawnDecor {
plantedItem(uint32) broadcast ram;
finishPlanting(uint32) airecv clsend;
finishRemoving(uint32) airecv clsend;
plantFlower(uint8, uint8, uint32) airecv clsend;
plantGagTree(uint8, uint8, uint32) airecv clsend;
plantStatuary(uint8, uint32) airecv clsend;
plantToonStatuary(uint8, uint16, uint32) airecv clsend;
plantNothing(uint8, uint32) airecv clsend;
plantFlower(uint8, uint8) airecv clsend;
plantGagTree(uint8, uint8) airecv clsend;
plantStatuary(uint8) airecv clsend;
plantToonStatuary(uint8, uint16) airecv clsend;
plantNothing(uint8) airecv clsend;
};
dclass DistributedGardenBox : DistributedLawnDecor {
@ -2584,7 +2575,6 @@ dclass DistributedGardenBox : DistributedLawnDecor {
};
dclass DistributedStatuary : DistributedLawnDecor {
setOwnerPlot(uint32) required broadcast ram;
setTypeIndex(uint8) required broadcast ram;
setWaterLevel(int8) required broadcast ram;
setGrowthLevel(int8) required broadcast ram;
@ -2602,11 +2592,10 @@ dclass DistributedChangingStatuary : DistributedStatuary {
};
dclass DistributedPlantBase : DistributedLawnDecor {
setOwnerPlot(uint32) required broadcast ram;
setTypeIndex(uint8) required broadcast ram;
setWaterLevel(int8) required broadcast ram;
setGrowthLevel(int8) required broadcast ram;
waterPlant(uint32) airecv clsend;
waterPlant() airecv clsend;
waterPlantDone() airecv clsend;
};
@ -2617,7 +2606,8 @@ dclass DistributedFlower : DistributedPlantBase {
dclass DistributedGagTree : DistributedPlantBase {
setWilted(int8) required broadcast ram;
requestHarvest(uint32) airecv clsend;
setFruiting(bool) required broadcast ram;
requestHarvest() airecv clsend;
};
struct golfData {

View file

@ -62,10 +62,9 @@ if ':' in host:
port = int(port)
simbase.air.connect(host, port)
gc.enable()
try:
run()
gc.enable()
except SystemExit:
raise
except Exception:

View file

@ -22,6 +22,11 @@ class CatalogGardenItem(CatalogItem.CatalogItem):
else:
return 100
def reachedPurchaseLimit(self, avatar):
if self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder or self in avatar.awardMailboxContents or self in avatar.onAwardOrder:
return 1
return 0
def getAcceptItemErrorText(self, retcode):
if retcode == ToontownGlobals.P_ItemAvailable:
return TTLocalizer.CatalogAcceptGarden
@ -45,7 +50,7 @@ class CatalogGardenItem(CatalogItem.CatalogItem):
def getPicture(self, avatar):
photoModel = GardenGlobals.Specials[self.gardenIndex]['photoModel']
if 'photoAnimation' in GardenGlobals.Specials[self.gardenIndex]:
if GardenGlobals.Specials[self.gardenIndex].has_key('photoAnimation'):
modelPath = photoModel + GardenGlobals.Specials[self.gardenIndex]['photoAnimation'][0]
animationName = GardenGlobals.Specials[self.gardenIndex]['photoAnimation'][1]
animationPath = photoModel + animationName
@ -74,9 +79,8 @@ class CatalogGardenItem(CatalogItem.CatalogItem):
def cleanupPicture(self):
CatalogItem.CatalogItem.cleanupPicture(self)
if hasattr(self, 'model') and self.model:
self.model.detachNode()
self.model = None
self.model.detachNode()
self.model = None
return
def output(self, store = -1):
@ -121,7 +125,7 @@ class CatalogGardenItem(CatalogItem.CatalogItem):
def getDeliveryTime(self):
if self.gardenIndex == GardenGlobals.GardenAcceleratorSpecial:
return 1
return 24 * 60
else:
return 0
@ -156,7 +160,7 @@ class CatalogGardenItem(CatalogItem.CatalogItem):
result = False
if canPlant < numBeansRequired:
result = True
if not result and self.gardenIndex in GardenGlobals.Specials and 'minSkill' in GardenGlobals.Specials[self.gardenIndex]:
if not result and GardenGlobals.Specials.has_key(self.gardenIndex) and GardenGlobals.Specials[self.gardenIndex].has_key('minSkill'):
minSkill = GardenGlobals.Specials[self.gardenIndex]['minSkill']
if avatar.shovelSkill < minSkill:
result = True

View file

@ -15,8 +15,10 @@ class CatalogGardenStarterItem(CatalogItem.CatalogItem):
def getPurchaseLimit(self):
return 0
def reachedPurchaseLimit(self, avatar):
return self in avatar.onOrder or self in avatar.mailboxContents or hasattr(avatar, 'gardenStarted') and avatar.getGardenStarted()
def reachedPurchaseLimit(self, avatar):
if self in avatar.onOrder or self in avatar.mailboxContents or self in avatar.onGiftOrder or self in avatar.awardMailboxContents or self in avatar.onAwardOrder or hasattr(avatar, 'gardenStarted') and avatar.getGardenStarted():
return 1
return 0
def saveHistory(self):
return 1
@ -29,13 +31,13 @@ class CatalogGardenStarterItem(CatalogItem.CatalogItem):
def recordPurchase(self, avatar, optional):
if avatar:
estate = simbase.air.estateManager.toon2estate.get(avatar)
self.notify.debug('rental -- has avatar')
estate = simbase.air.estateManager._lookupEstate(avatar)
if estate:
av = simbase.air.doId2do.get(avatar)
if av:
av.b_setGardenStarted(True)
print('garden saved')
estate.placeStarterGarden(avatar)
self.notify.debug('rental -- has estate')
estate.placeStarterGarden(avatar.doId)
else:
self.notify.warning('rental -- something not there')
return ToontownGlobals.P_ItemAvailable
def getPicture(self, avatar):

View file

@ -25,6 +25,7 @@ class CatalogToonStatueItem(CatalogGardenItem.CatalogGardenItem):
model, ival = self.makeFrameModel(toonStatuary.toon, 1)
self.pictureToonStatue = toonStatuary
self.hasPicture = True
toonStatuary.toon.setBin('gui-popup', 60)
return (model, ival)
def cleanupPicture(self):
@ -50,7 +51,7 @@ class CatalogToonStatueItem(CatalogGardenItem.CatalogGardenItem):
def getAllToonStatues(self):
self.statueList = []
for index in xrange(self.startPoseIndex, self.endPoseIndex + 1):
for index in range(self.startPoseIndex, self.endPoseIndex + 1):
self.statueList.append(CatalogToonStatueItem(index, 1, endPoseIndex=index))
return self.statueList

View file

@ -4,6 +4,3 @@ from toontown.estate.DistributedStatuaryAI import DistributedStatuaryAI
class DistributedAnimatedStatuaryAI(DistributedStatuaryAI):
notify = DirectNotifyGlobal.directNotify.newCategory("DistributedAnimatedStatuaryAI")
def __init__(self, air, species):
self.air = air
self.species = species

View file

@ -4,13 +4,6 @@ from toontown.estate.DistributedStatuaryAI import DistributedStatuaryAI
class DistributedChangingStatuaryAI(DistributedStatuaryAI):
notify = DirectNotifyGlobal.directNotify.newCategory("DistributedChangingStatuaryAI")
def __init__(self, air):
DistributedStatuaryAI.__init__(self, air)
self.air = air
self.growthLevel = -1
def setGrowthLevel(self, todo0):
pass
def setGrowthLevel(self, growthLevel):
self.growthLevel = growthLevel
def getGrowthLevel(self):
return self.growthLevel

File diff suppressed because it is too large Load diff

View file

@ -4,11 +4,15 @@ from toontown.estate import FlowerBase
from toontown.estate import GardenGlobals
from toontown.toontowngui import TTDialog
from toontown.toonbase import TTLocalizer
from DistributedGardenBox import DistributedGardenBox
DIRT_AS_WATER_INDICATOR = True
DIRT_MOUND_HEIGHT = 0.3
class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.FlowerBase):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedFlower')
deferFor = 2
def __init__(self, cr):
DistributedPlantBase.DistributedPlantBase.__init__(self, cr)
@ -17,16 +21,16 @@ class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.Fl
self.stickUp = 1.07
if DIRT_AS_WATER_INDICATOR:
self.stickUp += DIRT_MOUND_HEIGHT
self.collSphereRadius = 2.8
self.collSphereRadius = 2.2
self.shadowScale = 0.5
self.collSphereOffset = 0.0
self.dirtMound = None
self.sandMound = None
self.resultDialog = None
return
def delete(self):
DistributedPlantBase.DistributedPlantBase.delete(self)
del self.dirtMound
del self.sandMound
@ -34,9 +38,6 @@ class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.Fl
DistributedPlantBase.DistributedPlantBase.setTypeIndex(self, typeIndex)
self.setSpecies(typeIndex)
def getTypeIndex(self):
return self.typeIndex
def showWiltOrBloom(self):
if not self.model:
return
@ -52,7 +53,7 @@ class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.Fl
desat = wilt.find('**/*desat*')
bloom.hide()
leaves = wilt.findAllMatches('**/*leaf*')
for leafIndex in xrange(leaves.getNumPaths()):
for leafIndex in range(leaves.getNumPaths()):
leaf = leaves.getPath(leafIndex)
leaf.setColorScale(1.0, 0.3, 0.1, 1.0)
@ -132,7 +133,7 @@ class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.Fl
base.localAvatar.removeShovelRelatedDoId(self.doId)
base.localAvatar.setInGardenAction(self)
base.cr.playGame.getPlace().detectedGardenPlotUse()
self.sendUpdate('removeItem', [base.localAvatar.doId])
self.sendUpdate('removeItem', [])
def setWaterLevel(self, waterLevel):
DistributedPlantBase.DistributedPlantBase.setWaterLevel(self, waterLevel)
@ -140,18 +141,15 @@ class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.Fl
if self.model:
self.adjustWaterIndicator()
def getWaterLevel(self):
return self.waterLevel
def setGrowthLevel(self, growthLevel):
origGrowthLevel = self.growthLevel
self.growthLevel = growthLevel
if origGrowthLevel > -1:
self.loadModel()
self.makeMovieNode()
def getGrowthLevel(self):
return self.growthLevel
if hasattr(self, '_boxDoId'):
self.setBoxDoId(*self._boxDoId)
def makeMovieNode(self):
self.movieNode = self.rotateNode.attachNewNode('moviePos')
@ -200,4 +198,17 @@ class DistributedFlower(DistributedPlantBase.DistributedPlantBase, FlowerBase.Fl
self.resultDialog.destroy()
self.resultDialog = None
self.finishInteraction()
return
def setBoxDoId(self, boxId, index):
self._boxDoId = (boxId, index)
box = base.cr.doId2do[boxId]
x = GardenGlobals.FLOWER_POS[box.typeIndex][index]
self.setPos(0, 0, 0)
self.reparentTo(box)
self.setZ(1.5)
self.setX(x)
def stick2Ground(self):
pass

View file

@ -1,26 +1,145 @@
from direct.directnotify import DirectNotifyGlobal
from toontown.estate.DistributedPlantBaseAI import DistributedPlantBaseAI
from otp.ai.MagicWordGlobal import *
from DistributedPlantBaseAI import DistributedPlantBaseAI
from FlowerBase import FlowerBase
# TODO: Add flower to basket when picking, give shovel skill only if the
# flower is player's tier.
import GardenGlobals
import time
class DistributedFlowerAI(DistributedPlantBaseAI):
notify = DirectNotifyGlobal.directNotify.newCategory("DistributedFlowerAI")
ONE_DAY = 86400
def __init__(self, air):
DistributedPlantBaseAI.__init__(self, air)
self.air = air
self.typeIndex = None
class DistributedFlowerAI(DistributedPlantBaseAI, FlowerBase):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedFlowerAI')
def setTypeIndex(self, value):
DistributedPlantBaseAI.setTypeIndex(self, value)
FlowerBase.setSpecies(self, value)
def calculate(self, lastCheck):
now = int(time.time())
if lastCheck == 0:
lastCheck = now
grown = 0
# Water level
elapsed = now - lastCheck
while elapsed > ONE_DAY:
if self.waterLevel >= 0:
grown += 1
elapsed -= ONE_DAY
self.waterLevel -= 1
self.waterLevel = max(self.waterLevel, -2)
# Growth level
maxGrowth = self.growthThresholds[2]
newGL = min(self.growthLevel + grown, maxGrowth)
self.setGrowthLevel(newGL)
self.lastCheck = now - elapsed
self.update()
def update(self):
mdata = map(list, self.mgr.data['flowers'])
mdata[self.flowerIndex] = [self.getSpecies(), self.waterLevel, self.lastCheck, self.getGrowthLevel(), self.getVariety()]
self.mgr.data['flowers'] = mdata
self.mgr.update()
def removeItem(self, usingSatanPickAll=0):
avId = self.air.getAvatarIdFromSender()
if not usingSatanPickAll:
if avId != self.ownerDoId:
self.air.writeServerEvent('suspicious', avId, 'tried to remove someone else\'s flower!')
return
def setTypeIndex(self, typeIndex):
DistributedPlantBaseAI.setTypeIndex(self, typeIndex)
self.typeIndex = typeIndex
self.d_setMovie(GardenGlobals.MOVIE_REMOVE)
action = 'remove'
if self.getGrowthLevel() >= self.growthThresholds[2]:
action = 'pick'
def _remove(task):
if not self.air:
return
av = self.air.doId2do.get(self.ownerDoId)
if not av:
return
plot = self.mgr.placePlot(self.flowerIndex)
plot.flowerIndex = self.flowerIndex
plot.setPlot(self.plot)
plot.setOwnerIndex(self.ownerIndex)
plot.generateWithRequired(self.zoneId)
index = (0, 1, 2, 2, 2, 3, 3, 3, 4, 4)[self.flowerIndex]
idx = (0, 0, 0, 1, 2, 0, 1, 2, 0, 1)[self.flowerIndex]
plot.sendUpdate('setBoxDoId', [self.mgr._boxes[index].doId, idx])
self.air.writeServerEvent('%s-flower' % action, avId, plot=self.plot)
self.requestDelete()
self.mgr.flowers.remove(self)
mdata = map(list, self.mgr.data['flowers'])
mdata[self.flowerIndex] = self.mgr.getNullPlant()
self.mgr.data['flowers'] = mdata
self.mgr.update()
if action == 'pick':
av.b_setShovelSkill(av.getShovelSkill() + self.getValue())
av.addFlowerToBasket(self.getSpecies(), self.getVariety())
if task:
return task.done
if usingSatanPickAll:
_remove(None)
else:
taskMgr.doMethodLater(7, _remove, self.uniqueName('do-remove'))
@magicWord(category=CATEGORY_PROGRAMMER)
def satanGrowFlowers():
av = spellbook.getTarget()
estate = av.air.estateManager._lookupEstate(av)
if not estate:
return 'Estate not found!'
garden = estate.gardenManager.gardens.get(av.doId)
if not garden:
return 'Garden not found!'
def getTypeIndex(self):
return self.typeIndex
now = int(time.time())
i = 0
for flower in garden.flowers:
flower.b_setWaterLevel(5)
flower.b_setGrowthLevel(2)
flower.update()
i += 1
return '%d disgusting flowers grown' % i
@magicWord(category=CATEGORY_PROGRAMMER)
def satanPickAll():
av = spellbook.getTarget()
estate = av.air.estateManager._lookupEstate(av)
if not estate:
return 'Estate not found!'
garden = estate.gardenManager.gardens.get(av.doId)
if not garden:
return 'Garden not found!'
def setVariety(self, variety):
self.variety = variety
def getVariety(self):
return self.variety
i = 0
for flower in garden.flowers.copy():
if flower.getGrowthLevel() >= flower.growthThresholds[2]:
flower.removeItem(1)
i += 1
return '%d disgusting flowers picked' % i

View file

@ -29,7 +29,7 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase):
self.backupFruits = []
self.signHasBeenStuck2Ground = False
self.setName('DistributedGagTree')
return
self.fruiting = 0
def delete(self):
DistributedPlantBase.DistributedPlantBase.delete(self)
@ -79,7 +79,7 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase):
self.model.reparentTo(self.rotateNode)
if self.isFruiting() and not self.isWilted():
self.fruits = []
for i in xrange(1, self.maxFruit + 1):
for i in range(1, self.maxFruit + 1):
pos = self.model.find('**/locator' + str(i))
if pos and not pos.isEmpty():
fruit = self.prop.copyTo(self.model)
@ -141,8 +141,6 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase):
self.confirmDialog.destroy()
self.confirmDialog = None
if value > 0:
base.localAvatar.showGardeningGui()
base.localAvatar.removeShovelRelatedDoId(self.doId)
self.doPicking()
else:
self.finishInteraction()
@ -151,7 +149,7 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase):
def doPicking(self):
if not self.canBePicked():
return
self.sendUpdate('removeItem', [base.localAvatar.doId])
self.sendUpdate('removeItem', [])
def createBackupFruits(self):
if not hasattr(self, 'fruits'):
@ -175,6 +173,11 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase):
self.backupFruits.append(newFruit)
def clearBackupFruits(self):
if self.fruits:
for fruit in self.fruits:
fruit.removeNode()
self.fruits = None
self.backupFruits = []
def doHarvesting(self):
@ -184,14 +187,7 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase):
for fruit in self.backupFruits:
fruit.show()
self.sendUpdate('requestHarvest', [base.localAvatar.doId])
def hideItems(self):
if hasattr(self, 'fruits') and self.fruits:
seq = Parallel()
for item in self.fruits:
seq.append(LerpFunc(item.setAlphaScale, fromData=1, toData=0, duration=1))
seq.start()
self.sendUpdate('requestHarvest', [])
def getTrack(self):
return self.gagTrack
@ -268,7 +264,6 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase):
self.movie.append(Func(toon.loop, 'neutral'))
if avId == localAvatar.doId:
self.movie.append(Func(self.finishInteraction))
self.movie.append(Func(self.hideItems))
self.movie.append(Func(self.movieDone))
self.movie.append(Func(self.doResultDialog))
self.movie.start()
@ -299,7 +294,6 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase):
for fruit in self.backupFruits:
fruitTrack.append(Sequence(Func(fruit.show), LerpPosInterval(fruit, 1.5, pos, startPos=Point3(fruit.getX(), fruit.getY(), fruit.getZ() + self.model.getZ())), Func(fruit.removeNode)))
self.fruits = None
harvestTrack = Sequence(fruitTrack, Func(self.clearBackupFruits))
return harvestTrack
@ -343,7 +337,7 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase):
picker.traverse(render)
if queue.getNumEntries() > 0:
queue.sortEntries()
for index in xrange(queue.getNumEntries()):
for index in range(queue.getNumEntries()):
entry = queue.getEntry(index)
if DistributedLawnDecor.recurseParent(entry.getIntoNode(), 'terrain_DNARoot'):
self.signModel.wrtReparentTo(render)
@ -356,25 +350,7 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase):
return Task.done
def canBeHarvested(self):
myTrack, myLevel = GardenGlobals.getTreeTrackAndLevel(self.typeIndex)
levelsInTrack = []
levelTreeDict = {}
allGagTrees = base.cr.doFindAll('DistributedGagTree')
for gagTree in allGagTrees:
if gagTree.getOwnerId() == localAvatar.doId:
curTrack, curLevel = GardenGlobals.getTreeTrackAndLevel(gagTree.typeIndex)
if curTrack == myTrack:
levelsInTrack.append(curLevel)
levelTreeDict[curLevel] = gagTree
for levelToTest in xrange(myLevel):
if levelToTest not in levelsInTrack:
return False
curTree = levelTreeDict[levelToTest]
if not curTree.isGTEFullGrown():
return False
return True
return self.isFruiting()
def hasDependentTrees(self):
myTrack, myLevel = GardenGlobals.getTreeTrackAndLevel(self.typeIndex)
@ -403,8 +379,14 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase):
self.finishInteraction()
return
def velvetRoped(self):
return not base.cr.isPaid() and ToontownBattleGlobals.gagIsPaidOnly(self.gagTrack, self.gagLevel)
def allowedToPick(self):
return True
retval = True
if self.velvetRoped():
retval = False
return retval
def unlockPick(self):
retval = True
@ -417,3 +399,15 @@ class DistributedGagTree(DistributedPlantBase.DistributedPlantBase):
if inventory.numItem(self.gagTrack, self.gagLevel) >= inventory.getMax(self.gagTrack, self.gagLevel):
retval = False
return retval
def setFruiting(self, fruiting):
self.fruiting = fruiting
if self.model:
self.model.removeNode()
self.loadModel()
self.adjustWaterIndicator()
self.stick2Ground()
def isFruiting(self):
return self.fruiting

View file

@ -1,35 +1,223 @@
from direct.directnotify import DirectNotifyGlobal
from otp.ai.MagicWordGlobal import *
from toontown.estate.DistributedPlantBaseAI import DistributedPlantBaseAI
import GardenGlobals
import GardenGlobals, time
ONE_DAY = 86400
PROBLEM_WILTED = 1
PROBLEM_NOT_GROWN = 2
PROBLEM_HARVESTED_LATELY = 4
class DistributedGagTreeAI(DistributedPlantBaseAI):
notify = DirectNotifyGlobal.directNotify.newCategory("DistributedGagTreeAI")
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGagTreeAI')
GrowRate = config.GetBool('trees-grow-rate', 2)
def __init__(self, air):
DistributedPlantBaseAI.__init__(self, air)
self.air = air
def __init__(self, mgr):
DistributedPlantBaseAI.__init__(self, mgr)
self.wilted = 0
def announceGenerate(self):
DistributedPlantBaseAI.announceGenerate(self)
def delete(self):
DistributedPlantBaseAI.delete(self)
def disable(self):
DistributedPlantBaseAI.disable(self)
messenger.send(self.getEventName('generate'))
def setWilted(self, wilted):
self.wilted = wilted
def d_setWilted(self, wilted):
self.sendUpdate('setWilted', [wilted])
def b_setWilted(self, wilted):
self.setWilted(wilted)
self.d_setWilted(wilted)
def getWilted(self):
return self.wilted
def calculate(self, lastHarvested, lastCheck):
now = int(time.time())
if lastCheck == 0:
lastCheck = now
grown = 0
# Water level
elapsed = now - lastCheck
while elapsed > ONE_DAY:
if self.waterLevel >= 0:
grown += self.GrowRate
elapsed -= ONE_DAY
self.waterLevel -= 1
self.waterLevel = max(self.waterLevel, -2)
# Growth level
maxGrowth = self.growthThresholds[2]
newGL = min(self.growthLevel + grown, maxGrowth)
self.setGrowthLevel(newGL)
self.setWilted(self.waterLevel == -2)
self.lastCheck = now - elapsed
self.lastHarvested = lastHarvested
self.update()
def calcDependencies(self):
if self.getWilted():
return
missingPrevIndex = 0
track, value = GardenGlobals.getTreeTrackAndLevel(self.typeIndex)
while value:
value -= 1
if not self.mgr.hasTree(track, value):
self.b_setWilted(1)
continue
tree = self.mgr.getTree(track, value)
if not tree:
self.b_setWilted(1)
continue
self.accept(self.getEventName('going-down', 666), self.ignoreAll)
self.accept(self.getEventName('remove', track * 7 + value), self.calcDependencies)
def getEventName(self, string, typeIndex=None):
typeIndex = typeIndex if typeIndex is not None else self.typeIndex
return 'garden-%d-%d-%s' % (self.ownerDoId, typeIndex, string)
def delete(self):
messenger.send(self.getEventName('remove'))
self.ignoreAll()
DistributedPlantBaseAI.delete(self)
def update(self):
mdata = map(list, self.mgr.data['trees'])
mdata[self.treeIndex] = [self.typeIndex, self.waterLevel, self.lastCheck, self.getGrowthLevel(), self.lastHarvested]
self.mgr.data['trees'] = mdata
self.mgr.update()
def isFruiting(self):
problem = 0
if self.getWilted():
problem |= PROBLEM_WILTED
if self.getGrowthLevel() < self.growthThresholds[2]:
problem |= PROBLEM_NOT_GROWN
if (self.lastCheck - self.lastHarvested) < ONE_DAY:
problem |= PROBLEM_HARVESTED_LATELY
return problem
def getFruiting(self):
return self.isFruiting() == 0
def requestHarvest(self):
avId = self.air.getAvatarIdFromSender()
av = self.air.doId2do.get(avId)
if not av:
return
if avId != self.ownerDoId:
self.air.writeServerEvent('suspicious', avId, 'tried to harvest someone else\'s tree!')
return
problem = self.isFruiting()
if problem:
self.air.writeServerEvent('suspicious', avId, 'tried to harvest a tree that\'s not fruiting!', problem=problem)
return
def requestHarvest(self, doId):
# TODO: Actually harvest the gags and add them to toon inventory.
av = simbase.air.doId2do.get(doId)
harvested = 0
track, level = GardenGlobals.getTreeTrackAndLevel(self.typeIndex)
while av.inventory.addItem(track, level) > 0 and harvested < 10:
harvested += 1
self.sendUpdate('setMovie', [GardenGlobals.MOVIE_HARVEST, doId])
av.d_setInventory(av.getInventory())
self.lastHarvested = int(time.time())
self.sendUpdate('setFruiting', [self.getFruiting()])
self.d_setMovie(GardenGlobals.MOVIE_HARVEST)
self.update()
def removeItem(self):
avId = self.air.getAvatarIdFromSender()
self.d_setMovie(GardenGlobals.MOVIE_REMOVE)
def _remove(task):
if not self.air:
return
plot = self.mgr.placePlot(self.treeIndex)
plot.setPlot(self.plot)
plot.setPos(self.getPos())
plot.setH(self.getH())
plot.setOwnerIndex(self.ownerIndex)
plot.generateWithRequired(self.zoneId)
self.air.writeServerEvent('remove-tree', avId, plot=self.plot)
self.requestDelete()
self.mgr.trees.remove(self)
mdata = map(list, self.mgr.data['trees'])
mdata[self.treeIndex] = self.mgr.getNullPlant()
self.mgr.data['trees'] = mdata
self.mgr.update()
self.mgr.reconsiderAvatarOrganicBonus()
return task.done
taskMgr.doMethodLater(7, _remove, self.uniqueName('do-remove'))
def doGrow(self, grown):
maxGrowth = self.growthThresholds[2]
newGL = max(0, min(self.growthLevel + grown, maxGrowth))
oldGrowthLevel = self.growthLevel
self.b_setGrowthLevel(newGL)
self.update()
return newGL - oldGrowthLevel
@magicWord(category=CATEGORY_PROGRAMMER, types=[int, int, int])
def satanGrow(track, index, grown=21):
av = spellbook.getTarget()
estate = av.air.estateManager._lookupEstate(av)
if not estate:
return 'Estate not found!'
garden = estate.gardenManager.gardens.get(av.doId)
if not garden:
return 'Garden not found!'
tree = garden.getTree(track, index)
if not tree:
return 'Tree not found!'
result = tree.doGrow(grown)
return 'Satan has grown %d units!' % result
@magicWord(category=CATEGORY_PROGRAMMER, types=[int, int])
def satanFruit(track, index):
av = spellbook.getTarget()
estate = av.air.estateManager._lookupEstate(av)
if not estate:
return 'Estate not found!'
garden = estate.gardenManager.gardens.get(av.doId)
if not garden:
return 'Garden not found!'
tree = garden.getTree(track, index)
if not tree:
return 'Tree not found!'
tree.calculate(0, tree.lastCheck)
tree.sendUpdate('setFruiting', [tree.getFruiting()])
return 'Satan is now fruiting!'

View file

@ -1,9 +1,22 @@
from panda3d.core import *
from direct.distributed import DistributedObject
from direct.distributed.ClockDelta import *
from direct.directnotify import DirectNotifyGlobal
from direct.gui.DirectGui import *
from pandac.PandaModules import *
from toontown.toonbase.ToonBaseGlobal import *
from direct.gui.DirectGui import *
from pandac.PandaModules import *
from direct.distributed.ClockDelta import *
from toontown.toonbase import ToontownGlobals
from direct.distributed import DistributedObject
from direct.directnotify import DirectNotifyGlobal
from direct.fsm import ClassicFSM
from direct.fsm import State
from toontown.toon import Toon
from direct.showbase import RandomNumGen
from toontown.toonbase import TTLocalizer
import random
import random
import cPickle
from direct.showbase import PythonUtil
from toontown.hood import Place
import Estate
import HouseGlobals
class DistributedGarden(DistributedObject.DistributedObject):
@ -18,7 +31,7 @@ class DistributedGarden(DistributedObject.DistributedObject):
self.radius = 0
self.gridCells = 20
self.propTable = [None] * self.gridCells
for i in xrange(len(self.propTable)):
for i in range(len(self.propTable)):
self.propTable[i] = [None] * self.gridCells
self.dx = 1.0 / self.gridCells

View file

@ -4,25 +4,6 @@ from direct.distributed.DistributedObjectAI import DistributedObjectAI
class DistributedGardenAI(DistributedObjectAI):
notify = DirectNotifyGlobal.directNotify.newCategory("DistributedGardenAI")
def __init__(self, air):
DistributedObjectAI.__init__(self, air)
self.air = air
self.props = []
def sendNewProp(self, todo0, todo1, todo2, todo3):
pass
def generate(self):
DistributedObjectAI.generate(self)
def announceGenerate(self):
DistributedObjectAI.announceGenerate(self)
def disable(self):
DistributedObjectAI.disable(self)
def delete(self):
DistributedObjectAI.delete(self)
def setProps(self, props):
self.props = props
def d_sendNewProp(self, prop, x, y, z):
self.sendUpdate('sendNewProp', [prop, x, y, z])

View file

@ -11,7 +11,7 @@ from pandac.PandaModules import Vec3
class DistributedGardenBox(DistributedLawnDecor.DistributedLawnDecor):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGardenPlot')
def __init__(self, cr):
DistributedLawnDecor.DistributedLawnDecor.__init__(self, cr)
self.plantPath = NodePath('plantPath')
@ -19,25 +19,21 @@ class DistributedGardenBox(DistributedLawnDecor.DistributedLawnDecor):
self.plotScale = 1.0
self.plantingGuiDoneEvent = 'plantingGuiDone'
self.defaultModel = 'phase_5.5/models/estate/planterC'
def announceGenerate(self):
self.notify.debug('announceGenerate')
DistributedLawnDecor.DistributedLawnDecor.announceGenerate(self)
def doModelSetup(self):
if self.typeIndex == GardenGlobals.BOX_THREE:
self.defaultModel = 'phase_5.5/models/estate/planterA'
elif self.typeIndex == GardenGlobals.BOX_TWO:
self.defaultModel = 'phase_5.5/models/estate/planterC'
else:
self.defaultModel = 'phase_5.5/models/estate/planterB'
self.defaultModel = 'phase_5.5/models/estate/planterD'
self.collSphereOffset = 0.0
self.collSphereRadius = self.collSphereRadius * 1.41
self.plotScale = Vec3(1.0, 1.0, 1.0)
def setupShadow(self):
pass
def loadModel(self):
self.rotateNode = self.plantPath.attachNewNode('rotate')
self.model = None
@ -45,13 +41,13 @@ class DistributedGardenBox(DistributedLawnDecor.DistributedLawnDecor):
self.model.setScale(self.plotScale)
self.model.reparentTo(self.rotateNode)
self.stick2Ground()
return
def handleEnterPlot(self, entry = None):
pass
def handleExitPlot(self, entry = None):
DistributedLawnDecor.DistributedLawnDecor.handleExitPlot(self, entry)
def setTypeIndex(self, typeIndex):
self.typeIndex = typeIndex

View file

@ -4,13 +4,9 @@ from toontown.estate.DistributedLawnDecorAI import DistributedLawnDecorAI
class DistributedGardenBoxAI(DistributedLawnDecorAI):
notify = DirectNotifyGlobal.directNotify.newCategory("DistributedGardenBoxAI")
def __init__(self, air):
DistributedLawnDecorAI.__init__(self, air)
self.air = air
self.typeIndex = 0
def setTypeIndex(self, index):
self.typeIndex = index
self.index = index
def getTypeIndex(self):
return self.typeIndex
return self.index

View file

@ -2,6 +2,7 @@ import DistributedLawnDecor
from direct.directnotify import DirectNotifyGlobal
from direct.showbase.ShowBase import *
from direct.interval.IntervalGlobal import *
from DistributedGardenBox import DistributedGardenBox
import GardenGlobals
from toontown.toonbase import TTLocalizer
from toontown.estate import PlantingGUI
@ -14,6 +15,7 @@ import types
class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGardenPlot')
deferFor = 2
def __init__(self, cr):
DistributedLawnDecor.DistributedLawnDecor.__init__(self, cr)
@ -25,7 +27,6 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
self.defaultModel = 'phase_5.5/models/estate/dirt_mound'
self.colorScaler = Vec4(1, 1, 1, 1)
self.plantingGui = None
self.planted = None
return
def delete(self):
@ -84,8 +85,6 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
return self.getPlantingText()
def handleEnterPlot(self, entry = None):
#Force Gardens -Zach
base.localAvatar.setGardenStarted(True)
dist = self.getDistance(localAvatar)
if self.canBePlanted():
base.localAvatar.addShovelRelatedDoId(self.doId)
@ -110,12 +109,7 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
return plantText
def canBePlanted(self):
retval = True
if not base.localAvatar.doId == self.getOwnerId():
retval = False
if hasattr(self, 'planted') and self.planted:
retval = False
return retval
return base.localAvatar.doId == self.getOwnerId()
def plantSomething(self):
whatCanBePlanted = GardenGlobals.whatCanBePlanted(self.ownerIndex, self.plot)
@ -143,13 +137,14 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
recipeKey = GardenGlobals.getRecipeKey(recipeStr, special)
if recipeKey >= 0:
species, variety = GardenGlobals.getSpeciesVarietyGivenRecipe(recipeKey)
print 'RK>0', species, variety
if species >= 0 and variety >= 0:
self.sendUpdate('plantFlower', [species, variety, base.localAvatar.doId])
self.sendUpdate('plantFlower', [species, variety])
successPlanting = True
else:
self.notify.debug('%s %d is not a valid recipe' % (recipeStr, special))
burntBeans = len(recipeStr)
self.sendUpdate('plantNothing', [burntBeans, base.localAvatar.doId])
self.sendUpdate('plantNothing', [burntBeans])
if successPlanting:
flowerName = GardenGlobals.getFlowerVarietyName(species, variety)
stringToShow = TTLocalizer.getResultPlantedSomethingSentence(flowerName)
@ -209,11 +204,11 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
if species >= 205 and species <= 208:
successToonStatue = True
else:
self.sendUpdate('plantStatuary', [species, base.localAvatar.doId])
self.sendUpdate('plantStatuary', [species])
else:
self.notify.debug('%s %d is not a valid recipe' % (recipeStr, special))
burntBeans = len(recipeStr)
self.sendUpdate('plantNothing', [burntBeans, base.localAvatar.doId])
self.sendUpdate('plantNothing', [burntBeans])
if successPlanting:
itemName = GardenGlobals.PlantAttributes[species]['name']
stringToShow = TTLocalizer.getResultPlantedSomethingSentence(itemName)
@ -252,7 +247,7 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
base.localAvatar.showGardeningGui()
base.localAvatar.removeShovelRelatedDoId(self.doId)
if willPlant:
self.sendUpdate('plantToonStatuary', [species, dnaCode, base.localAvatar.doId])
self.sendUpdate('plantToonStatuary', [species, dnaCode])
else:
self.popupItemPlantingGui()
return
@ -271,21 +266,11 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
base.localAvatar.showGardeningGui()
base.localAvatar.removeShovelRelatedDoId(self.doId)
if willPlant:
self.sendUpdate('plantGagTree', [gagTrack, gagLevel, base.localAvatar.doId])
self.sendUpdate('plantGagTree', [gagTrack, gagLevel])
else:
self.finishInteraction()
return
def plantedItem(self, doId):
self.planted = doId
def removePlanted(self):
if self.planted:
item = base.cr.doId2do.get(self.planted)
if item:
item.delete()
self.planted = None
def setMovie(self, mode, avId):
if mode == GardenGlobals.MOVIE_PLANT:
self.doPlaceItemTrack(avId)
@ -316,8 +301,8 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
self.movie.append(Func(toon.detachShovel))
if self.model:
pos = self.model.getPos()
pos.setZ(pos[2] + 1)
animProp = LerpPosInterval(self.model, 3, pos, self.model.getPos())
pos.setZ(pos[2] - 1)
animProp = LerpPosInterval(self.model, 3, self.model.getPos(), pos)
shrinkProp = LerpScaleInterval(self.model, 3, scale=self.plotScale, startScale=0.01)
objAnimShrink = ParallelEndTogether(animProp, shrinkProp)
self.movie.append(objAnimShrink)
@ -325,16 +310,10 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
self.movie.append(Func(toon.loop, 'neutral'))
if avId == localAvatar.doId:
self.movie.append(Func(self.finishInteraction))
self.movie.append(Func(self.removePlanted))
self.movie.append(Func(self.movieDone))
self.movie.start()
def doPlaceItemTrack(self, avId, item = None):
if avId == 999999999:
pos = self.model.getPos()
pos.setZ(pos[2] - 1)
self.model.setPos(pos)
self.model.setScale(0.01)
return
toon = base.cr.doId2do.get(avId)
if not toon:
return
@ -348,24 +327,14 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
self.movie = Sequence(self.startCamIval(avId), moveTrack, Func(shovel.show), placeItemTrack)
if avId == localAvatar.doId:
self.expectingReplacement = 1
self.movie.append(Func(self.sendUpdate, 'finishPlanting', [avId]))
self.movie.append(Func(self.movieDone))
self.movie.start()
def generatePlaceItemTrack(self, toon, item):
sound = loader.loadSfx('phase_5.5/audio/sfx/burrow.ogg')
sound.setPlayRate(0.5)
placeItemTrack = Parallel()
placeItemTrack.append(Sequence(ActorInterval(toon, 'start-dig'),
Parallel(ActorInterval(toon, 'loop-dig', loop=1, duration=5.13),
Sequence(Wait(0.25),
SoundInterval(sound, node=toon, duration=0.55),
Wait(0.8),
SoundInterval(sound, node=toon, duration=0.55),
Wait(1.35),
SoundInterval(sound, node=toon, duration=0.55))),
ActorInterval(toon, 'start-dig', playRate=-1),
Func(toon.loop, 'neutral'),
Func(toon.detachShovel)))
placeItemTrack.append(Sequence(ActorInterval(toon, 'start-dig'), Parallel(ActorInterval(toon, 'loop-dig', loop=1, duration=5.13), Sequence(Wait(0.25), SoundInterval(sound, node=toon, duration=0.55), Wait(0.8), SoundInterval(sound, node=toon, duration=0.55), Wait(1.35), SoundInterval(sound, node=toon, duration=0.55))), ActorInterval(toon, 'start-dig', playRate=-1), Func(toon.loop, 'neutral'), Func(toon.detachShovel)))
if self.model:
pos = self.model.getPos()
pos.setZ(pos[2] - 1)
@ -374,12 +343,7 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
objAnimShrink = ParallelEndTogether(animProp, shrinkProp)
placeItemTrack.append(objAnimShrink)
if item:
placeItemTrack.append(Sequence(Func(item.reparentTo, toon.rightHand),
Wait(0.55),
Func(item.wrtReparentTo, render),
Parallel(LerpHprInterval(item, hpr=self.getHpr(render), duration=1.2),
ProjectileInterval(item, endPos=self.getPos(render), duration=1.2, gravityMult=0.45)),
Func(item.removeNode)))
placeItemTrack.append(Sequence(Func(item.reparentTo, toon.rightHand), Wait(0.55), Func(item.wrtReparentTo, render), Parallel(LerpHprInterval(item, hpr=self.getHpr(render), duration=1.2), ProjectileInterval(item, endPos=self.getPos(render), duration=1.2, gravityMult=0.45)), Func(item.removeNode)))
return placeItemTrack
def makeMovieNode(self):
@ -390,3 +354,20 @@ class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
self.stick2Ground()
else:
DistributedLawnDecor.DistributedLawnDecor.makeMovieNode(self)
def setBoxDoId(self, boxId, index):
box = base.cr.doId2do[boxId]
x = GardenGlobals.FLOWER_POS[box.typeIndex][index]
self.setPos(0, 0, 0)
self.reparentTo(box)
self.setZ(1.2)
self.setX(x)
def stick2Ground(self, *args, **kwargs):
plotType = GardenGlobals.whatCanBePlanted(self.ownerIndex, self.plot)
if plotType == GardenGlobals.FLOWER_TYPE:
return
return DistributedLawnDecor.DistributedLawnDecor.stick2Ground(self, *args, **kwargs)

View file

@ -1,189 +1,249 @@
from direct.directnotify import DirectNotifyGlobal
from toontown.estate.DistributedLawnDecorAI import DistributedLawnDecorAI
from DistributedToonStatuaryAI import DistributedToonStatuaryAI
from DistributedStatuaryAI import DistributedStatuaryAI
from DistributedGagTreeAI import DistributedGagTreeAI
from DistributedFlowerAI import DistributedFlowerAI
from otp.ai.MagicWordGlobal import *
from DistributedLawnDecorAI import DistributedLawnDecorAI
import GardenGlobals
import datetime
slots2plots = {
0: GardenGlobals.plots0,
1: GardenGlobals.plots1,
2: GardenGlobals.plots2,
3: GardenGlobals.plots3,
4: GardenGlobals.plots4,
5: GardenGlobals.plots5
}
class DistributedGardenPlotAI(DistributedLawnDecorAI):
notify = DirectNotifyGlobal.directNotify.newCategory("DistributedGardenPlotAI")
def __init__(self, air):
DistributedLawnDecorAI.__init__(self, air)
self.air = air
self.planted = None
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGardenPlotAI')
def announceGenerate(self):
DistributedLawnDecorAI.announceGenerate(self)
def delete(self):
DistributedLawnDecorAI.delete(self)
def disable(self):
DistributedLawnDecorAI.disable(self)
def finishPlanting(self, avId):
self.planted.generateWithRequired(self.zoneId)
self.addData()
self.sendUpdate('plantedItem', [self.planted.doId])
self.planted.sendUpdate('setMovie', [GardenGlobals.MOVIE_FINISHPLANTING, avId])
def finishRemoving(self, avId):
self.removeData()
self.planted.removeNode()
self.planted.delete()
simbase.air.removeObject(self.planted.doId)
self.planted = None
self.sendUpdate('setMovie', [GardenGlobals.MOVIE_FINISHREMOVING, avId])
def addData(self):
estate = simbase.air.doId2do.get(self.getEstate())
plantedAt = int(datetime.datetime.now().strftime('%Y%m%d%H%M')) # TODO: Possibly store this in mongodb/cPickle instead.
if isinstance(self.planted, DistributedFlowerAI):
data = [
self.getPlot(),
GardenGlobals.FLOWER_TYPE,
self.planted.getTypeIndex(),
self.planted.getVariety(),
self.planted.getWaterLevel(),
self.planted.getGrowthLevel(),
0,
plantedAt,
plantedAt
]
elif isinstance(self.planted, DistributedGagTreeAI):
data = [
self.getPlot(),
GardenGlobals.GAG_TREE_TYPE,
self.planted.getTypeIndex(),
0,
self.planted.getWaterLevel(),
self.planted.getGrowthLevel(),
0,
plantedAt,
plantedAt
]
elif isinstance(self.planted, DistributedToonStatuaryAI):
data = [
self.getPlot(),
GardenGlobals.TOON_STATUARY_TYPE,
self.planted.getTypeIndex(),
0,
self.planted.getWaterLevel(),
self.planted.getGrowthLevel(),
self.planted.getOptional(),
plantedAt,
plantedAt
]
elif isinstance(self.planted, DistributedStatuaryAI):
data = [
self.getPlot(),
GardenGlobals.STATUARY_TYPE,
self.planted.getTypeIndex(),
0,
self.planted.getWaterLevel(),
self.planted.getGrowthLevel(),
0,
plantedAt,
plantedAt
]
else:
self.plotType = GardenGlobals.whatCanBePlanted(self.ownerIndex, self.plot)
self.__plantingAvId = 0
def __initialSanityCheck(self, wantedType=None, forceOwner=False):
if self.__plantingAvId:
# Busy, silently ignore
return
estate.items[self.getOwnerIndex()].append(tuple(data))
estate.updateItems()
avId = self.air.getAvatarIdFromSender()
av = self.air.doId2do.get(avId)
if not av:
self.air.writeServerEvent('suspicious', avId, 'called DistributedGardenPlotAI method outside shard!')
return
if wantedType is not None and self.plotType != wantedType:
self.air.writeServerEvent('suspicious', avId, 'called incorrect DistributedGardenPlotAI method!', plotType=self.plotType,
wantedType=wantedType)
return self.d_interactionDenied()
if avId != self.ownerDoId and not forceOwner:
self.air.writeServerEvent('suspicious', avId, 'called someone else\'s DistributedGardenPlotAI plant method!',
ownerDoId=self.ownerDoId)
return self.d_interactionDenied()
return av
def removeData(self):
estate = simbase.air.doId2do.get(self.getEstate())
dataIndex = -1
for n, item in enumerate(estate.items[self.getOwnerIndex()]):
if item[0] == self.getPlot():
dataIndex = n
if dataIndex >= 0:
del estate.items[self.getOwnerIndex()][dataIndex]
estate.updateItems()
def plantFlower(self, species, variety, usingSatanFlowerAll=0):
av = self.__initialSanityCheck(GardenGlobals.FLOWER_TYPE if not usingSatanFlowerAll else None, usingSatanFlowerAll)
if not av:
return
def invalid(problem):
msg = 'tried to plant flower but something went wrong: %s' % problem
self.notify.warning('%d %s' % (av.doId, msg))
self.air.writeServerEvent('suspicious', av.doId, msg)
if not usingSatanFlowerAll:
return self.d_setMovie(GardenGlobals.MOVIE_PLANT_REJECTED)
attr = GardenGlobals.PlantAttributes.get(species, {})
if attr.get('plantType') != GardenGlobals.FLOWER_TYPE:
return invalid('invalid species: %d' % species)
if variety >= len(attr['varieties']):
return invalid('invalid variety: %d' % variety)
if not usingSatanFlowerAll:
cost = len(GardenGlobals.Recipes[attr['varieties'][variety][0]]['beans'])
av.takeMoney(cost)
self.d_setMovie(GardenGlobals.MOVIE_PLANT)
def _plant(task):
flower = self.mgr.plantFlower(self.flowerIndex, species, variety, plot=self,
ownerIndex=self.ownerIndex, plotId=self.plot,
waterLevel=0)
index = (0, 1, 2, 2, 2, 3, 3, 3, 4, 4)[self.flowerIndex]
idx = (0, 0, 0, 1, 2, 0, 1, 2, 0, 1)[self.flowerIndex]
flower.sendUpdate('setBoxDoId', [self.mgr._boxes[index].doId, idx])
if not usingSatanFlowerAll:
flower.d_setMovie(GardenGlobals.MOVIE_FINISHPLANTING, self.__plantingAvId)
flower.d_setMovie(GardenGlobals.MOVIE_CLEAR, self.__plantingAvId)
self.air.writeServerEvent('plant-flower', self.__plantingAvId, species=species, variety=variety,
plot=self.plot, name=attr.get('name', 'unknown satan flower'))
if task:
return task.done
if usingSatanFlowerAll:
_plant(None)
else:
taskMgr.doMethodLater(7, _plant, self.uniqueName('do-plant'))
self.__plantingAvId = av.doId
return 1
def plantGagTree(self, track, index):
av = self.__initialSanityCheck(GardenGlobals.GAG_TREE_TYPE)
if not av:
return
for i in xrange(index):
if not self.mgr.hasTree(track, i):
msg = 'tried to plant tree but an index is missing: %d' % index
self.notify.warning('%d %s' % (av.doId, msg))
self.air.writeServerEvent('suspicious', av.doId, msg)
return self.d_setMovie(GardenGlobals.MOVIE_PLANT_REJECTED)
if self.mgr.hasTree(track, index):
msg = 'tried to plant tree but gag already planted'
self.notify.warning('%d %s' % (av.doId, msg))
self.air.writeServerEvent('suspicious', av.doId, msg)
return self.d_setMovie(GardenGlobals.MOVIE_PLANT_REJECTED)
if av.inventory.useItem(track, index) == -1:
msg = 'tried to plant tree but not carrying selected gag'
self.notify.warning('%d %s' % (av.doId, msg))
self.air.writeServerEvent('suspicious', av.doId, msg)
return self.d_setMovie(GardenGlobals.MOVIE_PLANT_REJECTED)
av.d_setInventory(av.getInventory())
self.d_setMovie(GardenGlobals.MOVIE_PLANT)
def _plant(task):
if not self.air:
return
tree = self.mgr.plantTree(self.treeIndex, track * 7 + index, plot=self, ownerIndex=self.ownerIndex,
plotId=self.plot, pos=(self.getPos(), self.getH()))
tree.d_setMovie(GardenGlobals.MOVIE_FINISHPLANTING, self.__plantingAvId)
tree.d_setMovie(GardenGlobals.MOVIE_CLEAR, self.__plantingAvId)
self.air.writeServerEvent('plant-tree', self.__plantingAvId, track=track, index=index, plot=self.plot)
return task.done
taskMgr.doMethodLater(7, _plant, self.uniqueName('do-plant'))
self.__plantingAvId = av.doId
def plantFlower(self, species, variety, toon):
#free for now
#av = simbase.air.doId2do.get(toon)
#av.takeMoney(GardenGlobals.getNumBeansRequired(species, variety))
self.planted = DistributedFlowerAI(self.air)
self.planted.setEstate(self.getEstate())
self.planted.setOwnerPlot(self.doId)
self.planted.setPlot(self.getPlot())
self.planted.setHeading(self.getHeading())
self.planted.setPosition(*self.getPosition())
self.planted.setOwnerIndex(self.getOwnerIndex())
self.planted.setWaterLevel(0)
self.planted.setGrowthLevel(0)
self.planted.setTypeIndex(species)
self.planted.setVariety(variety)
self.sendUpdate('setMovie', [GardenGlobals.MOVIE_PLANT, toon])
def plantStatuary(self, species):
av = self.__initialSanityCheck(GardenGlobals.STATUARY_TYPE)
if not av:
return
def invalid(problem):
msg = 'tried to plant statuary but something went wrong: %s' % problem
self.notify.warning('%d %s' % (av.doId, msg))
self.air.writeServerEvent('suspicious', av.doId, msg)
return self.d_setMovie(GardenGlobals.MOVIE_PLANT_REJECTED)
attr = GardenGlobals.PlantAttributes.get(species, {})
if attr.get('plantType') != GardenGlobals.STATUARY_TYPE:
return invalid('invalid species: %d' % species)
it = species - 100
if it == 134:
it = 135
if not av.removeGardenItem(it, 1):
return invalid('av doesn\'t own item: %d' % species)
self.d_setMovie(GardenGlobals.MOVIE_PLANT)
def _plant(task):
if not self.air:
return
statuary = self.mgr.placeStatuary(self.mgr.S_pack(0, 0, species, 0), plot=self,
ownerIndex=self.ownerIndex, plotId=self.plot,
pos=(self.getPos(), self.getH()), generate=False)
statuary.generateWithRequired(self.zoneId)
statuary.d_setMovie(GardenGlobals.MOVIE_FINISHPLANTING, self.__plantingAvId)
statuary.d_setMovie(GardenGlobals.MOVIE_CLEAR, self.__plantingAvId)
self.air.writeServerEvent('plant-statuary', self.__plantingAvId, species=species, plot=self.plot)
return task.done
taskMgr.doMethodLater(7, _plant, self.uniqueName('do-plant'))
self.__plantingAvId = av.doId
def plantGagTree(self, track, level, toon):
#free for now
#av = simbase.air.doId2do.get(toon)
#av.inventory.useItem(track, level)
#av.d_setInventory(av.inventory.makeNetString())
self.planted = DistributedGagTreeAI(self.air)
self.planted.setEstate(self.getEstate())
self.planted.setOwnerPlot(self.doId)
self.planted.setPlot(self.getPlot())
self.planted.setHeading(self.getHeading())
self.planted.setPosition(*self.getPosition())
self.planted.setOwnerIndex(self.getOwnerIndex())
self.planted.setTypeIndex(GardenGlobals.getTreeTypeIndex(track, level))
self.planted.setWaterLevel(0)
self.planted.setGrowthLevel(0)
self.sendUpdate('setMovie', [GardenGlobals.MOVIE_PLANT, toon])
def plantToonStatuary(self, species, dnaCode):
av = self.__initialSanityCheck(GardenGlobals.STATUARY_TYPE)
if not av:
return
def invalid(problem):
msg = 'tried to plant statuary but something went wrong: %s' % problem
self.notify.warning('%d %s' % (av.doId, msg))
self.air.writeServerEvent('suspicious', av.doId, msg)
return self.d_setMovie(GardenGlobals.MOVIE_PLANT_REJECTED)
attr = GardenGlobals.PlantAttributes.get(species, {})
if attr.get('plantType') != GardenGlobals.STATUARY_TYPE:
return invalid('invalid species: %d' % species)
if not av.removeGardenItem(species - 100, 1):
return invalid('av doesn\'t own item: %d' % species)
self.d_setMovie(GardenGlobals.MOVIE_PLANT)
def _plant(task):
if not self.air:
return
statuary = self.mgr.placeStatuary(self.mgr.S_pack(dnaCode, 0, species, 0), plot=self,
ownerIndex=self.ownerIndex, plotId=self.plot,
pos=(self.getPos(), self.getH()), generate=False)
statuary.generateWithRequired(self.zoneId)
statuary.d_setMovie(GardenGlobals.MOVIE_FINISHPLANTING, self.__plantingAvId)
self.air.writeServerEvent('plant-statuary', self.__plantingAvId, species=species, plot=self.plot)
return task.done
taskMgr.doMethodLater(7, _plant, self.uniqueName('do-plant'))
self.__plantingAvId = av.doId
def plantStatuary(self, species, toon):
#free for now
#av = simbase.air.doId2do.get(toon)
#av.takeMoney(GardenGlobals.getNumBeansRequired(species, 0))
self.planted = DistributedStatuaryAI(self.air)
self.planted.setEstate(self.getEstate())
self.planted.setOwnerPlot(self.doId)
self.planted.setPlot(self.getPlot())
self.planted.setHeading(self.getHeading())
self.planted.setPosition(*self.getPosition())
self.planted.setOwnerIndex(self.getOwnerIndex())
self.planted.setTypeIndex(species)
self.planted.setWaterLevel(0)
self.planted.setGrowthLevel(0)
self.sendUpdate('setMovie', [GardenGlobals.MOVIE_PLANT, toon])
def plantToonStatuary(self, species, dnaCode, toon):
#free for now
#av = simbase.air.doId2do.get(toon)
#av.takeMoney(GardenGlobals.getNumBeansRequired(species, 0))
self.planted = DistributedToonStatuaryAI(self.air)
self.planted.setEstate(self.getEstate())
self.planted.setOwnerPlot(self.doId)
self.planted.setPlot(self.getPlot())
self.planted.setHeading(self.getHeading())
self.planted.setPosition(*self.getPosition())
self.planted.setOwnerIndex(self.getOwnerIndex())
self.planted.setTypeIndex(species)
self.planted.setWaterLevel(0)
self.planted.setGrowthLevel(0)
self.planted.setOptional(dnaCode)
self.sendUpdate('setMovie', [GardenGlobals.MOVIE_PLANT, toon])
def plantNothing(self, burntBeans, toon):
# TODO: Fix exploit.
sendAvId = self.air.getAvatarIdFromSender()
av = self.air.doId2do.get(sendAvId)
def plantNothing(self, burntBeans):
av = self.__initialSanityCheck()
if av:
av.takeMoney(burntBeans)
self.planted = None
@magicWord(category=CATEGORY_PROGRAMMER, types=[int, int])
def satanFlowerAll(species=49, variety=0):
invoker = spellbook.getInvoker()
av = spellbook.getTarget()
estate = av.air.estateManager._lookupEstate(av)
if not estate:
return 'Estate not found!'
garden = estate.gardenManager.gardens.get(av.doId)
if not garden:
return 'Garden not found!'
i = 0
for obj in garden.objects.copy():
if isinstance(obj, DistributedGardenPlotAI):
if obj.plotType != GardenGlobals.FLOWER_TYPE:
continue
if not obj.plantFlower(species, variety, 1):
return 'Error on plot %d' % i
i += 1
def troll(task):
channel = invoker.GetPuppetConnectionChannel(invoker.doId)
av.air.sendSysMsg('OMG YOU SOLD YOUR SOUL NOOOOOOOOOOOOOOOOOOOO', channel)
return task.done
taskMgr.doMethodLater(6.66, troll, 'satan-troll')
return '%d disgusting flowers planted' % i
@magicWord(category=CATEGORY_PROGRAMMER)
def gibSpecials():
av = spellbook.getTarget()
av.gardenSpecials = []
for x in (100, 101, 103, 105, 106, 107, 108, 130, 131, 135):
av.addGardenItem(x, 99)

View file

@ -1,4 +1,4 @@
from panda3d.core import *
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *
from direct.distributed import ClockDelta
from direct.showbase.PythonUtil import lerp
@ -16,6 +16,7 @@ from otp.otpbase import OTPGlobals
from toontown.estate import GardenGlobals
def recurseParent(intoNode, ParentName):
# funny fact: cogtown had a func like this
parent = intoNode.getParent(0)
if not parent or parent.getName() == 'render':
return 0
@ -50,6 +51,7 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast
return
def setHeading(self, h):
self.notify.debug('setting h')
DistributedNode.DistributedNode.setH(self, h)
def generateInit(self):
@ -93,6 +95,11 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast
if not self.rotateNode:
self.rotateNode = self.plantPath.attachNewNode('rotate')
self.model = None
if __dev__:
self.model = loader.loadModel(self.defaultModel)
self.model.setScale(0.4, 0.4, 0.1)
self.model.reparentTo(self.rotateNode)
return
def setupShadow(self):
self.shadowJoint = self.rotateNode.attachNewNode('shadow')
@ -121,6 +128,7 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast
self.accept(self.exitMessageName, self.handleExitPlot)
def handleEnterPlot(self, optional = None):
self.notify.debug('handleEnterPlot %d' % self.doId)
self.sendUpdate('plotEntered', [])
def handleExitPlot(self, optional = None):
@ -142,12 +150,6 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast
taskMgr.remove(self.uniqueName('adjust tree'))
return
def setEstate(self, estate):
self.estate = estate
def getEstate(self):
return self.estate
def setPos(self, x, y, z):
DistributedNode.DistributedNode.setPos(self, x, y, z)
self.stick2Ground()
@ -175,7 +177,7 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast
picker.traverse(render)
if queue.getNumEntries() > 0:
queue.sortEntries()
for index in xrange(queue.getNumEntries()):
for index in range(queue.getNumEntries()):
entry = queue.getEntry(index)
if recurseParent(entry.getIntoNode(), 'terrain_DNARoot'):
self.movieNode.setZ(entry.getSurfacePoint(self)[2])
@ -184,7 +186,7 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast
picker.traverse(render)
if queue.getNumEntries() > 0:
queue.sortEntries()
for index in xrange(queue.getNumEntries()):
for index in range(queue.getNumEntries()):
entry = queue.getEntry(index)
if recurseParent(entry.getIntoNode(), 'terrain_DNARoot'):
self.setZ(entry.getSurfacePoint(render)[2] + self.stickUp + 0.1)
@ -197,12 +199,12 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast
def stickParts(self):
pass
def setH(self, h):
DistributedNode.DistributedNode.setH(self, h)
def setPlot(self, plot):
self.plot = plot
def setH(self, h):
DistributedNode.DistributedNode.setH(self, h)
def getPlot(self):
return self.plot
@ -242,7 +244,7 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast
base.localAvatar.hideShovelButton()
base.localAvatar.hideWateringCanButton()
self.startInteraction()
self.sendUpdate('removeItem', [base.localAvatar.doId])
self.sendUpdate('removeItem', [])
def generateToonMoveTrack(self, toon):
node = NodePath('tempNode')
@ -261,10 +263,7 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast
finalY = node.getY(render)
finalZ = node.getZ(render)
node.removeNode()
toonTrack = Sequence(Parallel(ActorInterval(toon, 'walk', loop=True, duration=1),
Parallel(LerpPosInterval(toon, 1.0, Point3(finalX, finalY, toon.getZ(render)), fluid=True, bakeInStart=False)),
LerpHprInterval(toon, 1.0, hpr=hpr)),
Func(toon.loop, 'neutral'))
toonTrack = Sequence(Parallel(ActorInterval(toon, 'walk', loop=True, duration=1), Parallel(LerpPosInterval(toon, 1.0, Point3(finalX, finalY, toon.getZ(render)), fluid=True, bakeInStart=False)), LerpHprInterval(toon, 1.0, hpr=hpr)), Func(toon.loop, 'neutral'))
return toonTrack
def unprint(self, string):
@ -288,16 +287,13 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast
def startCamIval(self, avId):
track = Sequence()
if avId == localAvatar.doId:
track = Sequence(Func(base.localAvatar.disableSmartCameraViews),
Func(base.localAvatar.setCameraPosForPetInteraction))
track = Sequence(Func(base.localAvatar.disableSmartCameraViews), Func(base.localAvatar.setCameraPosForPetInteraction))
return track
def stopCamIval(self, avId):
track = Sequence()
if avId == localAvatar.doId:
track = Sequence(Func(base.localAvatar.unsetCameraPosForPetInteraction),
Wait(0.8),
Func(base.localAvatar.enableSmartCameraViews))
track = Sequence(Func(base.localAvatar.unsetCameraPosForPetInteraction), Wait(0.8), Func(base.localAvatar.enableSmartCameraViews))
return track
def canBeWatered(self):
@ -332,8 +328,6 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast
if not toon:
return
self.finishMovies()
if avId == localAvatar.doId:
self.startInteraction()
self.model.setTransparency(1)
self.model.setAlphaScale(1)
shovel = toon.attachShovel()
@ -341,11 +335,9 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast
moveTrack = self.generateToonMoveTrack(toon)
digupTrack = self.generateDigupTrack(toon)
self.movie = Sequence(self.startCamIval(avId), moveTrack, Func(shovel.show), digupTrack)
self.movie.append(Func(base.cr.removeObject, self.doId))
if avId == localAvatar.doId:
self.expectingReplacement = 1
plotAv = base.cr.doId2do.get(self.getOwnerPlot())
self.movie.append(Func(plotAv.sendUpdate, 'finishRemoving', [avId]))
# self.expectingReplacement = 1
self.movie.append(Func(self.movieDone))
self.movie.start()
def generateDigupTrack(self, toon):
@ -354,22 +346,7 @@ class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCast
pos = self.model.getPos()
pos.setZ(pos[2] - 1)
track = Parallel()
sq = Sequence(ActorInterval(toon, 'start-dig'),
Parallel(ActorInterval(toon, 'loop-dig', loop=1, duration=5.13),
Sequence(Wait(0.25),
SoundInterval(sound, node=toon, duration=0.55),
Wait(0.8),
SoundInterval(sound, node=toon, duration=0.55),
Wait(1.35),
SoundInterval(sound, node=toon, duration=0.55))),
ActorInterval(toon, 'start-dig', playRate=-1),
LerpFunc(self.model.setAlphaScale, fromData=1, toData=0, duration=1))
if hasattr(self, 'signModel'):
sq.append(Parallel(LerpFunc(self.signModel.setAlphaScale, fromData=1, toData=0, duration=1),
LerpScaleInterval(self.signModel, 1, 0, 1)))
sq.append(Func(toon.loop, 'neutral'))
sq.append(Func(toon.detachShovel))
track.append(sq)
track.append(Sequence(ActorInterval(toon, 'start-dig'), Parallel(ActorInterval(toon, 'loop-dig', loop=1, duration=5.13), Sequence(Wait(0.25), SoundInterval(sound, node=toon, duration=0.55), Wait(0.8), SoundInterval(sound, node=toon, duration=0.55), Wait(1.35), SoundInterval(sound, node=toon, duration=0.55))), ActorInterval(toon, 'start-dig', playRate=-1), LerpFunc(self.model.setAlphaScale, fromData=1, toData=0, duration=1), Func(toon.loop, 'neutral'), Func(toon.detachShovel)))
return track
def doFinishPlantingTrack(self, avId):

View file

@ -1,68 +1,40 @@
from direct.directnotify import DirectNotifyGlobal
from direct.distributed.DistributedNodeAI import DistributedNodeAI
import GardenGlobals
class DistributedLawnDecorAI(DistributedNodeAI):
notify = DirectNotifyGlobal.directNotify.newCategory("DistributedLawnDecorAI")
def __init__(self, air):
DistributedNodeAI.__init__(self, air)
self.air = air
self.plot = None
self.ownerIndex = None
def announceGenerate(self):
DistributedNodeAI.announceGenerate(self)
def delete(self):
DistributedNodeAI.delete(self)
def disable(self):
DistributedNodeAI.disable(self)
def setEstate(self, estate):
self.estate = estate
def getEstate(self):
return self.estate
def __init__(self, mgr):
self.mgr = mgr
DistributedNodeAI.__init__(self, self.mgr.air)
self.plot = 0
self.ownerIndex = 0
def setPlot(self, plot):
self.plot = plot
def getPlot(self):
return self.plot
def setOwnerIndex(self, index):
self.ownerIndex = index
def getHeading(self):
return self.getH()
def getPosition(self):
return self.getPos()
def setOwnerIndex(self, ownerIndex):
self.ownerIndex = ownerIndex
self.ownerDoId = self.mgr.gardenMgr.mgr.toons[ownerIndex]
self.owner = self.air.doId2do.get(self.ownerDoId)
def getOwnerIndex(self):
return self.ownerIndex
def setPosition(self, x, y, z):
self.position = (x, y, z)
def getPosition(self):
return self.position
def setHeading(self, heading):
self.heading = heading
def getHeading(self):
return self.heading
def plotEntered(self):
pass
def removeItem(self, avId):
self.inUseBy = avId
self.d_setMovie(GardenGlobals.MOVIE_REMOVE, avId)
def d_setMovie(self, mode, avId):
def d_setMovie(self, mode, avId=None):
if avId is None:
avId = self.air.getAvatarIdFromSender()
self.sendUpdate('setMovie', [mode, avId])
def movieDone(self):
if hasattr(self, 'inUseBy'):
del self.inUseBy
def interactionDenied(self, todo0):
pass
def d_interactionDenied(self):
self.sendUpdate('interactionDenied', [self.air.getAvatarIdFromSender()])

View file

@ -44,12 +44,6 @@ class DistributedPlantBase(DistributedLawnDecor.DistributedLawnDecor):
DistributedLawnDecor.DistributedLawnDecor.setupShadow(self)
self.adjustWaterIndicator()
def setOwnerPlot(self, owner):
self.ownerPlot = owner
def getOwnerPlot(self):
return self.ownerPlot
def setTypeIndex(self, typeIndex):
self.typeIndex = typeIndex
self.attributes = GardenGlobals.PlantAttributes[typeIndex]
@ -69,9 +63,7 @@ class DistributedPlantBase(DistributedLawnDecor.DistributedLawnDecor):
self.waterLevel = waterLevel
def getWaterLevel(self):
if hasattr(self, 'waterLevel'):
return self.waterLevel
return 0
return self.waterLevel
def setGrowthLevel(self, growthLevel):
self.growthLevel = growthLevel
@ -105,11 +97,11 @@ class DistributedPlantBase(DistributedLawnDecor.DistributedLawnDecor):
def handleWatering(self):
self.startInteraction()
self.sendUpdate('waterPlant', [localAvatar.doId])
self.sendUpdate('waterPlant')
def __handleWatering(self, plantToWaterId):
if plantToWaterId == self.doId:
self.sendUpdate('waterPlant', [localAvatar.doId])
self.sendUpdate('waterPlant')
else:
self.notify.debug('not sending water plant')

View file

@ -1,84 +1,81 @@
from direct.directnotify import DirectNotifyGlobal
from toontown.estate.DistributedLawnDecorAI import DistributedLawnDecorAI
import GardenGlobals
import datetime
class DistributedPlantBaseAI(DistributedLawnDecorAI):
notify = DirectNotifyGlobal.directNotify.newCategory("DistributedPlantBaseAI")
def __init__(self, air):
DistributedLawnDecorAI.__init__(self, air)
self.air = air
self.growthLevel = -1
def announceGenerate(self):
DistributedLawnDecorAI.announceGenerate(self)
def delete(self):
DistributedLawnDecorAI.delete(self)
def disable(self):
DistributedLawnDecorAI.disable(self)
def setOwnerPlot(self, owner):
self.ownerPlot = owner
def getOwnerPlot(self):
return self.ownerPlot
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPlantBaseAI')
def __init__(self, mgr):
DistributedLawnDecorAI.__init__(self, mgr)
self.typeIndex = 0
self.waterLevel = 0
self.growthLevel = 0
def setTypeIndex(self, typeIndex):
self.typeIndex = typeIndex
self.attributes = GardenGlobals.PlantAttributes[typeIndex]
self.name = self.attributes['name']
self.plantType = self.attributes['plantType']
self.growthThresholds = self.attributes['growthThresholds']
self.maxWaterLevel = self.attributes['maxWaterLevel']
self.minWaterLevel = self.attributes['minWaterLevel']
def d_setTypeIndex(self, typeIndex):
self.sendUpdate('setTypeIndex', [typeIndex])
def b_setTypeIndex(self, typeIndex):
self.setTypeIndex(typeIndex)
self.d_setTypeIndex(typeIndex)
def getTypeIndex(self):
return self.typeIndex
def setWaterLevel(self, water):
self.waterLevel = water
def setWaterLevel(self, waterLevel):
self.waterLevel = waterLevel
def d_setWaterLevel(self, waterLevel):
self.sendUpdate('setWaterLevel', [waterLevel])
def b_setWaterLevel(self, waterLevel):
self.setWaterLevel(waterLevel)
self.d_setWaterLevel(waterLevel)
def getWaterLevel(self):
return self.waterLevel
def setGrowthLevel(self, growth):
self.growthLevel = growth
def setGrowthLevel(self, growthLevel):
self.growthLevel = growthLevel
def d_setGrowthLevel(self, growthLevel):
self.sendUpdate('setGrowthLevel', [growthLevel])
def b_setGrowthLevel(self, growthLevel):
self.setGrowthLevel(growthLevel)
self.d_setGrowthLevel(growthLevel)
def getGrowthLevel(self):
return self.growthLevel
def waterPlant(self, avId):
# TODO: Proper water threshold for watering can type.
# Not supposed to be 16 for all watering cans.
self.lastWateredBy = avId
newLevel = self.waterLevel + 1
if newLevel > self.maxWaterLevel:
self.setWaterLevel(self.maxWaterLevel)
else:
self.setWaterLevel(newLevel)
self.sendUpdate('setMovie', [GardenGlobals.MOVIE_WATER, avId])
self.sendUpdate('setWaterLevel', [self.getWaterLevel()])
def waterPlant(self):
av = self.air.doId2do.get(self.air.getAvatarIdFromSender())
if not av:
return
level = max(1, self.getWaterLevel() + av.getWateringCan() + 1)
level = min(20, level)
self.b_setWaterLevel(level)
self.d_setMovie(GardenGlobals.MOVIE_WATER)
self.update()
def waterPlantDone(self):
if hasattr(self, 'lastWateredBy'):
av = simbase.air.doId2do.get(self.lastWateredBy)
skill = av.getWateringCanSkill()
skill += GardenGlobals.WateringCanAttributes[av.wateringCan]['skillPts'] / 100
av.b_setWateringCanSkill(skill)
del self.lastWateredBy
estate = simbase.air.doId2do.get(self.getEstate())
dataIndex = -1
# TODO: Possibly store this in mongodb/cPickle instead.
for n, item in enumerate(estate.items[self.getOwnerIndex()]):
if item[0] == self.getPlot():
dataIndex = n
if dataIndex >= 0:
dtime = int(datetime.datetime.now().strftime('%Y%m%d%H%M'))
data = list(estate.items[self.getOwnerIndex()][dataIndex])
data[4] = self.getWaterLevel()
data[8] = dtime
estate.items[self.getOwnerIndex()][dataIndex] = tuple(data)
estate.updateItems()
av = self.air.doId2do.get(self.air.getAvatarIdFromSender())
if not av:
return
if self.waterLevel < 6:
av.b_setWateringCanSkill(av.getWateringCanSkill() + 1)
else:
av.b_setWateringCanSkill(av.getWateringCanSkill())
self.d_setMovie(GardenGlobals.MOVIE_CLEAR)
def update(self):
pass

View file

@ -37,22 +37,16 @@ class DistributedStatuary(DistributedLawnDecor.DistributedLawnDecor):
attrib = GardenGlobals.PlantAttributes[self.typeIndex]
self.stick2Ground()
def setOwnerPlot(self, owner):
self.ownerPlot = owner
def getOwnerPlot(self):
return self.ownerPlot
def setTypeIndex(self, typeIndex):
self.typeIndex = typeIndex
self.name = GardenGlobals.PlantAttributes[typeIndex]['name']
self.plantType = GardenGlobals.PlantAttributes[typeIndex]['plantType']
self.modelPath = GardenGlobals.PlantAttributes[typeIndex]['model']
self.pinballScore = None
if 'pinballScore' in GardenGlobals.PlantAttributes[typeIndex]:
if GardenGlobals.PlantAttributes[typeIndex].has_key('pinballScore'):
self.pinballScore = GardenGlobals.PlantAttributes[typeIndex]['pinballScore']
self.worldScale = 1.0
if 'worldScale' in GardenGlobals.PlantAttributes[typeIndex]:
if GardenGlobals.PlantAttributes[typeIndex].has_key('worldScale'):
self.worldScale = GardenGlobals.PlantAttributes[typeIndex]['worldScale']
return

View file

@ -1,33 +1,66 @@
from direct.directnotify import DirectNotifyGlobal
from toontown.estate.DistributedLawnDecorAI import DistributedLawnDecorAI
from DistributedLawnDecorAI import DistributedLawnDecorAI
import GardenGlobals
import time
FOUR_DAYS = 86400 * 4
class DistributedStatuaryAI(DistributedLawnDecorAI):
notify = DirectNotifyGlobal.directNotify.newCategory("DistributedStatuaryAI")
def calculate(self, lastCheck):
self.attributes = GardenGlobals.PlantAttributes[self.index]
self.growthThresholds = self.attributes.get('growthThresholds', (0, 0))
now = int(time.time())
self.lastCheck = lastCheck
if self.lastCheck == 0:
self.lastCheck = now
def __init__(self, air):
DistributedLawnDecorAI.__init__(self, air)
self.air = air
def setTypeIndex(self, typeIndex):
self.typeIndex = typeIndex
self.growthLevel = min((now - self.lastCheck) // FOUR_DAYS, self.growthThresholds[-1] + 1)
self.update()
def getTypeIndex(self):
return self.typeIndex
def setOwnerPlot(self, owner):
self.ownerPlot = owner
def getOwnerPlot(self):
return self.ownerPlot
def setWaterLevel(self, waterLevel):
self.waterLevel = waterLevel
return self.index
def getWaterLevel(self):
return self.waterLevel
def setGrowthLevel(self, growthLevel):
self.growthLevel = growthLevel
return 1
def getGrowthLevel(self):
return self.growthLevel
def getOptional(self):
return self.data
def update(self):
self.mgr.data['statuary'] = self.mgr.S_pack(self.data, self.lastCheck, self.index, self.growthLevel)
self.mgr.update()
def removeItem(self):
avId = self.air.getAvatarIdFromSender()
self.d_setMovie(GardenGlobals.MOVIE_REMOVE)
def _remove(task):
if not self.air:
return
plot = self.mgr.placePlot(-1)
plot.setPlot(self.plot)
plot.setPos(self.getPos())
plot.setH(self.getH())
plot.setOwnerIndex(self.ownerIndex)
plot.generateWithRequired(self.zoneId)
self.air.writeServerEvent('remove-statuary', avId, plot=self.plot)
self.requestDelete()
self.mgr.objects.remove(self)
self.mgr.data['statuary'] = 0
self.mgr.update()
return task.done
taskMgr.doMethodLater(7, _remove, self.uniqueName('do-remove'))

View file

@ -2,7 +2,7 @@ from toontown.estate import DistributedStatuary
from toontown.estate import DistributedLawnDecor
from direct.directnotify import DirectNotifyGlobal
from direct.showbase.ShowBase import *
from panda3d.core import *
from pandac.PandaModules import *
from toontown.toon import Toon
from toontown.toon import ToonDNA
import GardenGlobals
@ -46,7 +46,7 @@ class DistributedToonStatuary(DistributedStatuary.DistributedStatuary):
self.model.setScale(self.worldScale * 1.5, self.worldScale * 1.5, self.worldScale)
self.getToonPropertiesFromOptional()
dna = ToonDNA.ToonDNA()
dna.newToonFromProperties(self.headType, self.torsoType, self.legType, self.gender, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
dna.newToonFromProperties(self.headType, self.torsoType, self.legType, self.gender, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
self.setupStoneToon(dna)
self.poseToonFromTypeIndex(self.typeIndex)
self.toon.reparentTo(self.model)
@ -112,7 +112,7 @@ class DistributedToonStatuary(DistributedStatuary.DistributedStatuary):
if sleeves:
sleeves.setTexture(desatSleeveTex, 1)
bottoms = torso.findAllMatches('**/torso-bot*')
for bottomNum in xrange(0, bottoms.getNumPaths()):
for bottomNum in range(0, bottoms.getNumPaths()):
bottom = bottoms.getPath(bottomNum)
if bottom:
if self.toon.style.torso[1] == 's':

View file

@ -4,12 +4,6 @@ from toontown.estate.DistributedStatuaryAI import DistributedStatuaryAI
class DistributedToonStatuaryAI(DistributedStatuaryAI):
notify = DirectNotifyGlobal.directNotify.newCategory("DistributedToonStatuaryAI")
def __init__(self, air):
DistributedStatuaryAI.__init__(self, air)
self.air = air
def setOptional(self, todo0):
pass
def setOptional(self, optional):
self.optional = optional
def getOptional(self):
return self.optional

View file

@ -239,7 +239,7 @@ class LoadEstateFSM(FSM):
estate.pets = []
self.estate.toons = self.toonIds
self.estate.updateToons()
#self.estate.updateToons()
# Gotcha! Now we need to load houses:
self.demand('LoadHouses')

View file

@ -12,7 +12,6 @@ INVALID_TYPE = -1
GAG_TREE_TYPE = 0
FLOWER_TYPE = 1
STATUARY_TYPE = 2
TOON_STATUARY_TYPE = 3
WATERING_CAN_SMALL = 0
WATERING_CAN_MEDIUM = 1
WATERING_CAN_LARGE = 2
@ -34,7 +33,7 @@ WateringMult = 2
def getWateringCanPower(wateringCan, wateringCanSkill):
numBoxes = 0
for curWateringCan in xrange(wateringCan + 1):
for curWateringCan in range(wateringCan + 1):
wateringCanAttrib = WateringCanAttributes[curWateringCan]
curBoxes = wateringCanAttrib['numBoxes']
skill = wateringCanAttrib['skillPts']
@ -309,7 +308,7 @@ def getTreeTypeIndex(track, level):
NUM_GAGS = 7 * 7
for i in xrange(NUM_GAGS):
for i in range(NUM_GAGS):
track, level = getTreeTrackAndLevel(i)
if level <= 6:
name = TTLocalizer.BattleGlobalAvPropStrings[track][level] + TTLocalizer.GardenGagTree
@ -495,7 +494,7 @@ ShovelAttributes = {0: {'numBoxes': 2,
def getShovelPower(shovel, shovelSkill):
numBoxes = 0
for curShovel in xrange(shovel + 1):
for curShovel in range(shovel + 1):
shovelAttrib = ShovelAttributes[curShovel]
curBoxes = shovelAttrib['numBoxes']
skill = shovelAttrib['skillPts']
@ -597,8 +596,8 @@ def getSpeciesVarietyGivenRecipe(recipeKey):
attrib = PlantAttributes[species]
if attrib['plantType'] == GAG_TREE_TYPE:
continue
if 'varieties' in attrib:
for variety in xrange(len(attrib['varieties'])):
if attrib.has_key('varieties'):
for variety in range(len(attrib['varieties'])):
if attrib['varieties'][variety][0] == recipeKey:
return (species, variety)
@ -609,14 +608,14 @@ def getNumBeansRequired(species, variety):
retval = -1
if not PlantAttributes.get(species):
return retval
if 'varieties' not in PlantAttributes[species]:
if not PlantAttributes[species].has_key('varieties'):
return retval
if variety >= len(PlantAttributes[species]['varieties']):
return -1
recipeKey = PlantAttributes[species]['varieties'][variety][0]
recipe = Recipes.get(recipeKey)
if recipe:
if 'beans' in recipe:
if recipe.has_key('beans'):
retval = len(recipe['beans'])
return retval
@ -653,7 +652,7 @@ def validateRecipes(notify):
def validatePlantAttributes(notify):
uniqueRecipes = []
flowerRecipeDistribution = []
for i in xrange(getNumberOfShovelBoxes() + 1):
for i in range(getNumberOfShovelBoxes() + 1):
flowerRecipeDistribution.append([])
for key in PlantAttributes.keys():
@ -675,7 +674,7 @@ def validatePlantAttributes(notify):
newInfo = (getFlowerVarietyName(key, list(varieties).index(variety)), Recipes[recipeNum]['beans'], TTLocalizer.FlowerColorStrings[variety[1]])
flowerRecipeDistribution[recipeLength].append(newInfo)
for numBeans in xrange(len(flowerRecipeDistribution)):
for numBeans in range(len(flowerRecipeDistribution)):
notify.debug('%d flowers with %d beans' % (len(flowerRecipeDistribution[numBeans]), numBeans))
for flower in flowerRecipeDistribution[numBeans]:
notify.debug(' %s, beans = %s, color=%s' % (flower[0], flower[1], flower[2]))
@ -683,7 +682,7 @@ def validatePlantAttributes(notify):
notify.debug('plant attributes are ok')
plots0 = [(0,
plots0 = ((0,
0,
0.0,
FLOWER_TYPE),
@ -758,45 +757,45 @@ plots0 = [(0,
(-100,
-43,
-90.0,
STATUARY_TYPE)]
plots1 = [(85.0,
-67.0,
STATUARY_TYPE))
plots1 = ((0,
0,
0.0,
FLOWER_TYPE),
(75,
-72,
(1,
0,
0.0,
FLOWER_TYPE),
(89.865,
-71.7725,
(2,
0,
0.0,
FLOWER_TYPE),
(91.0,
-74.0,
(2,
1,
0.0,
FLOWER_TYPE),
(92.135,
-76.2275,
(2,
2,
0.0,
FLOWER_TYPE),
(75.865,
-78.7725,
(3,
0,
0.0,
FLOWER_TYPE),
(77,
-81,
(3,
1,
0.0,
FLOWER_TYPE),
(78.135,
-83.2275,
(3,
2,
0.0,
FLOWER_TYPE),
(86.6518,
-86.6576,
(4,
0,
0.0,
FLOWER_TYPE),
(89.3482,
-85.3424,
(4,
1,
0.0,
FLOWER_TYPE),
(62,
@ -834,8 +833,8 @@ plots1 = [(85.0,
(47,
-82,
-30.0,
STATUARY_TYPE)]
plots2 = [(0,
STATUARY_TYPE))
plots2 = ((0,
0,
0.0,
FLOWER_TYPE),
@ -910,8 +909,8 @@ plots2 = [(0,
(-97,
-114,
-60.0,
STATUARY_TYPE)]
plots3 = [(0,
STATUARY_TYPE))
plots3 = ((0,
0,
0.0,
FLOWER_TYPE),
@ -986,8 +985,8 @@ plots3 = [(0,
(117,
27,
102.0,
STATUARY_TYPE)]
plots4 = [(0,
STATUARY_TYPE))
plots4 = ((0,
0,
0.0,
FLOWER_TYPE),
@ -1062,8 +1061,8 @@ plots4 = [(0,
(16,
87,
-140.0,
STATUARY_TYPE)]
plots5 = [(0,
STATUARY_TYPE))
plots5 = ((0,
0,
0.0,
FLOWER_TYPE),
@ -1138,7 +1137,7 @@ plots5 = [(0,
(-55,
70,
213.0,
STATUARY_TYPE)]
STATUARY_TYPE))
estatePlots = (plots0,
plots1,
plots2,
@ -1148,7 +1147,8 @@ estatePlots = (plots0,
BOX_ONE = 1
BOX_TWO = 2
BOX_THREE = 3
flowerBoxes0 = [(-62.5,
FLOWER_POS = (None, (0,), (-1.5, 1.5), (-3.5, 0, 3.5))
flowerBoxes0 = ((-62.5,
-52.5,
182.0,
BOX_ONE),
@ -1167,8 +1167,8 @@ flowerBoxes0 = [(-62.5,
(-57,
-33,
0.0,
BOX_TWO)]
flowerBoxes1 = [(85.0,
BOX_TWO))
flowerBoxes1 = ((85.0,
-67.0,
26.0,
BOX_ONE),
@ -1187,8 +1187,8 @@ flowerBoxes1 = [(85.0,
(88,
-86,
206.0,
BOX_TWO)]
flowerBoxes2 = [(-62,
BOX_TWO))
flowerBoxes2 = ((-62,
-112,
350.0,
BOX_ONE),
@ -1207,8 +1207,8 @@ flowerBoxes2 = [(-62,
(-71,
-129,
169.0,
BOX_TWO)]
flowerBoxes3 = [(72,
BOX_TWO))
flowerBoxes3 = ((72,
5,
265.0,
BOX_ONE),
@ -1227,8 +1227,8 @@ flowerBoxes3 = [(72,
(54,
12,
86.0,
BOX_TWO)]
flowerBoxes4 = [(35.5,
BOX_TWO))
flowerBoxes4 = ((35.5,
70,
152.0,
BOX_ONE),
@ -1247,8 +1247,8 @@ flowerBoxes4 = [(35.5,
(47,
86,
-19.0,
BOX_TWO)]
flowerBoxes5 = [(-26.5,
BOX_TWO))
flowerBoxes5 = ((-26.5,
37.5,
318.0,
BOX_ONE),
@ -1267,7 +1267,7 @@ flowerBoxes5 = [(-26.5,
(-45,
31,
124.0,
BOX_TWO)]
BOX_TWO))
estateBoxes = (flowerBoxes0,
flowerBoxes1,
flowerBoxes2,