from toontown.estate import DistributedPlantBase from direct.interval.IntervalGlobal import * from direct.directnotify import DirectNotifyGlobal from direct.showbase import PythonUtil from toontown.toonbase import ToontownBattleGlobals from toontown.toontowngui import TTDialog from toontown.toonbase import TTLocalizer import GardenGlobals import HouseGlobals from direct.task import Task from panda3d.core import * from otp.otpbase import OTPGlobals from toontown.estate import DistributedLawnDecor DIRT_AS_WATER_INDICATOR = True class DistributedGagTree(DistributedPlantBase.DistributedPlantBase): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGagTree') def __init__(self, cr): DistributedPlantBase.DistributedPlantBase.__init__(self, cr) base.tree = self self.collSphereRadius = 4.2 self.confirmDialog = None self.resultDialog = None self.dirtMound = None self.sandMound = None self.needToPlant = 0 self.needToLoad = 0 self.backupFruits = [] self.signHasBeenStuck2Ground = False self.setName('DistributedGagTree') self.fruiting = 0 def delete(self): DistributedPlantBase.DistributedPlantBase.delete(self) del self.prop del self.prop2 del self.dirtMound del self.sandMound self.signModel.removeNode() self.signModel = None return def setTypeIndex(self, typeIndex): DistributedPlantBase.DistributedPlantBase.setTypeIndex(self, typeIndex) track, level = GardenGlobals.getTreeTrackAndLevel(typeIndex) self.gagTrack = track self.gagLevel = level invModel = loader.loadModel('phase_3.5/models/gui/inventory_icons') propName = ToontownBattleGlobals.AvPropsNew[track][level] self.prop = invModel.find('**/' + propName) self.prop.setScale(7) invModel.removeNode() invModel2 = loader.loadModel('phase_3.5/models/gui/inventory_icons') propName = ToontownBattleGlobals.AvPropsNew[track][level] self.prop2 = invModel2.find('**/' + propName) self.prop2.setScale(7) self.filename = self.attributes['filename'] self.maxFruit = self.attributes['maxFruit'] if hasattr(self, 'needToLoad'): if self.needToLoad: self.loadModel() def loadModel(self): if not hasattr(self, 'filename'): self.needToLoad = 1 return if not self.rotateNode: self.rotateNode = self.plantPath.attachNewNode('rotate') all = loader.loadModel(self.filename) self.modelName = self.getModelName() if self.isWilted(): self.modelName += '_wilt' self.model = all.find('**/' + self.modelName) all.detachNode() shadow = self.model.find('**/shadow1') if shadow: shadow.hide() self.model.reparentTo(self.rotateNode) if self.isFruiting() and not self.isWilted(): self.fruits = [] for i in xrange(1, self.maxFruit + 1): pos = self.model.find('**/locator' + str(i)) if pos and not pos.isEmpty(): fruit = self.prop.copyTo(self.model) fruit.setPos(pos, 0, 0, 0) fruit.setScale(13) self.fruits.append(fruit) self.createBackupFruits() if DIRT_AS_WATER_INDICATOR: self.dirtMound = loader.loadModel('phase_5.5/models/estate/dirt_mound') self.dirtMound.reparentTo(self.model) self.sandMound = loader.loadModel('phase_5.5/models/estate/sand_mound') self.sandMound.reparentTo(self.model) self.adjustGrowth() self.signModel = loader.loadModel('phase_5.5/models/estate/garden_sign.bam') self.signModel.setPos(3.5, 0, 0.025) self.signModel.reparentTo(self.rotateNode) owner = self.getOwnerIndex() color = HouseGlobals.houseColors[owner] for geomName in ('sign', 'sign1'): sign = self.signModel.find('**/' + geomName) if sign: sign.setColor(*color) self.prop.setPos(0.1, -0.17, 1.63) self.prop.reparentTo(self.signModel) self.prop2.setPos(0.15, 0.17, 1.63) self.prop2.setH(self.prop.getH() + 180) self.prop2.reparentTo(self.signModel) self.needToLoad = 0 if self.needToPlant: self.stickParts() def setupShadow(self): DistributedPlantBase.DistributedPlantBase.setupShadow(self) self.adjustGrowth() def makeMovieNode(self): self.movieNode = self.rotateNode.attachNewNode('moviePos') self.movieNode.setPos(0, -5, 0) self.createBackupFruits() def handlePicking(self): messenger.send('wakeup') if self.isFruiting() and self.canBeHarvested(): self.startInteraction() self.doHarvesting() return fullName = self.name text = TTLocalizer.ConfirmRemoveTree % {'tree': fullName} if self.hasDependentTrees(): text += TTLocalizer.ConfirmWontBeAbleToHarvest self.confirmDialog = TTDialog.TTDialog(style=TTDialog.YesNo, text=text, command=self.confirmCallback) self.confirmDialog.show() self.startInteraction() return def confirmCallback(self, value): self.confirmDialog.destroy() self.confirmDialog = None if value > 0: self.doPicking() else: self.finishInteraction() return def doPicking(self): if not self.canBePicked(): return self.sendUpdate('removeItem', []) def createBackupFruits(self): if not hasattr(self, 'fruits'): return if not self.fruits: return if not hasattr(self, 'movieNode'): return if not self.movieNode: return if self.movieNode.isEmpty(): return if not self.signHasBeenStuck2Ground: return if not self.backupFruits: for fruit in self.fruits: newFruit = fruit.copyTo(render) newFruit.setPos(fruit.getPos(render)) newFruit.setH(self.movieNode.getH(render)) newFruit.hide() 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): if not self.canBePicked(): return if hasattr(self, 'backupFruits'): for fruit in self.backupFruits: fruit.show() self.sendUpdate('requestHarvest', []) def getTrack(self): return self.gagTrack def getGagLevel(self): return self.gagLevel def setWaterLevel(self, waterLevel): self.waterLevel = waterLevel self.adjustWaterIndicator() def setGrowthLevel(self, growthLevel): self.growthLevel = growthLevel if self.model: newModelName = self.getModelName() if True: self.model.removeNode() self.loadModel() self.adjustWaterIndicator() self.stick2Ground() else: self.adjustGrowth() def adjustGrowth(self): newScale = self.growthLevel + 1 if newScale > 1: newScale = 1 shadowScale = 2.5 collScale = 1.5 if self.isSeedling(): shadowScale = 1 collScale = 1 if self.shadowJoint: self.shadowJoint.setScale(shadowScale) if DIRT_AS_WATER_INDICATOR: dirtMoundScale = shadowScale * 1.5 dirtMoundDepth = 2.0 if self.isEstablished(): dirtMoundScale = shadowScale * 1.2 self.dirtMound.setScale(dirtMoundScale, dirtMoundScale, dirtMoundDepth) self.sandMound.setScale(dirtMoundScale, dirtMoundScale, dirtMoundDepth) self.adjustWaterIndicator() def setWilted(self, wilted): self.wilted = wilted def isWilted(self): return self.wilted def setMovie(self, mode, avId): if mode == GardenGlobals.MOVIE_HARVEST: self.doHarvestTrack(avId) elif mode == GardenGlobals.MOVIE_WATER: self.doWaterTrack(avId) elif mode == GardenGlobals.MOVIE_FINISHPLANTING: self.doFinishPlantingTrack(avId) elif mode == GardenGlobals.MOVIE_REMOVE: self.doDigupTrack(avId) def doFinishPlantingTrack(self, avId): toon = base.cr.doId2do.get(avId) if not toon: return self.finishMovies() self.movie = Sequence() if self.model: self.model.setTransparency(1) self.model.setAlphaScale(0) self.movie.append(LerpFunc(self.model.setAlphaScale, fromData=0, toData=1, duration=3)) if self.signModel: self.signModel.hide() self.movie.append(Func(self.signModel.show)) self.movie.append(LerpScaleInterval(self.signModel, 1, 1, 0)) self.movie.append(Func(toon.loop, 'neutral')) if avId == localAvatar.doId: self.movie.append(Func(self.finishInteraction)) self.movie.append(Func(self.movieDone)) self.movie.append(Func(self.doResultDialog)) self.movie.start() def doHarvestTrack(self, avId): toon = base.cr.doId2do.get(avId) if not toon: return self.finishMovies() moveTrack = self.generateToonMoveTrack(toon) harvestTrack = self.generateHarvestTrack(toon) self.movie = Sequence(self.startCamIval(avId), moveTrack, harvestTrack, self.stopCamIval(avId)) if avId == localAvatar.doId: self.movie.append(Func(self.finishInteraction)) self.movie.append(Func(self.movieDone)) self.movie.start() def setupShadow(self): if DIRT_AS_WATER_INDICATOR: pass else: DistributedPlantBase.DistributedPlantBase.setupShadow(self) def generateHarvestTrack(self, toon): pos = toon.getPos(render) pos.setZ(pos.getZ() + 2) fruitTrack = Parallel() 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))) harvestTrack = Sequence(fruitTrack, Func(self.clearBackupFruits)) return harvestTrack def adjustWaterIndicator(self): DistributedPlantBase.DistributedPlantBase.adjustWaterIndicator(self) if self.dirtMound: curWaterLevel = self.waterLevel if curWaterLevel > self.maxWaterLevel: curWaterLevel = self.maxWaterLevel if curWaterLevel > 0: darkestColorScale = 0.4 lightestColorScale = 1.0 scaleRange = lightestColorScale - darkestColorScale scaleIncrement = scaleRange / self.maxWaterLevel darker = lightestColorScale - scaleIncrement * curWaterLevel self.dirtMound.setColorScale(darker, darker, darker, 1.0) self.sandMound.hide() self.dirtMound.show() else: self.sandMound.show() self.dirtMound.hide() def stickParts(self): if not hasattr(self, 'signModel'): self.needToPlant = 1 return Task.done if self.signModel.isEmpty(): return Task.done testPath = NodePath('testPath') testPath.reparentTo(render) cRay = CollisionRay(0.0, 0.0, 40000.0, 0.0, 0.0, -1.0) cRayNode = CollisionNode(self.uniqueName('estate-FloorRay')) cRayNode.addSolid(cRay) cRayNode.setFromCollideMask(OTPGlobals.FloorBitmask) cRayNode.setIntoCollideMask(BitMask32.allOff()) cRayNodePath = testPath.attachNewNode(cRayNode) queue = CollisionHandlerQueue() picker = CollisionTraverser() picker.addCollider(cRayNodePath, queue) testPath.setPos(self.signModel.getX(render), self.signModel.getY(render), 0) picker.traverse(render) if queue.getNumEntries() > 0: queue.sortEntries() for index in xrange(queue.getNumEntries()): entry = queue.getEntry(index) if DistributedLawnDecor.recurseParent(entry.getIntoNode(), 'terrain_DNARoot'): self.signModel.wrtReparentTo(render) self.signModel.setZ(entry.getSurfacePoint(render)[2] + self.stickUp + 0.1) self.signModel.wrtReparentTo(self.rotateNode) self.signHasBeenStuck2Ground = True self.createBackupFruits() return Task.done return Task.done def canBeHarvested(self): return self.isFruiting() def hasDependentTrees(self): myTrack, myLevel = GardenGlobals.getTreeTrackAndLevel(self.typeIndex) allGagTrees = base.cr.doFindAll('DistributedGagTree') for gagTree in allGagTrees: if gagTree.getOwnerId() == localAvatar.doId: curTrack, curLevel = GardenGlobals.getTreeTrackAndLevel(gagTree.typeIndex) if curTrack == myTrack: if myLevel < curLevel: return True return False def doResultDialog(self): self.startInteraction() curTrack, curLevel = GardenGlobals.getTreeTrackAndLevel(self.typeIndex) species = GardenGlobals.getTreeTypeIndex(curTrack, curLevel) treeName = GardenGlobals.PlantAttributes[species]['name'] stringToShow = TTLocalizer.getResultPlantedSomethingSentence(treeName) self.resultDialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=stringToShow, command=self.resultsCallback) def resultsCallback(self, value): if self.resultDialog: self.resultDialog.destroy() self.resultDialog = None self.finishInteraction() return def allowedToPick(self): return True def unlockPick(self): retval = True toon = base.localAvatar inventory = toon.inventory load = inventory.totalProps maxCarry = toon.getMaxCarry() if load >= maxCarry and not self.gagLevel > ToontownBattleGlobals.LAST_REGULAR_GAG_LEVEL: retval = False 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