oldschool-toontown/toontown/estate/DistributedGagTree.py
Little Cat 1801d2b9fb
all: replace pandac.PandaModules imports.
UD/AI + Client boots up.
2022-12-16 20:40:57 -04:00

428 lines
16 KiB
Python

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.toontowngui.TeaserPanel import TeaserPanel
from toontown.toonbase import TTLocalizer
from . import GardenGlobals
from . 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._teaserPanel = None
self.setName('DistributedGagTree')
return
def delete(self):
DistributedPlantBase.DistributedPlantBase.delete(self)
if self._teaserPanel:
self._teaserPanel.destroy()
self._teaserPanel = None
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 range(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():
if self.velvetRoped():
self._teaserPanel = TeaserPanel(pageName='pickGags')
localAvatar._gagTreeVelvetRoped = None
else:
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):
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)))
self.fruits = None
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 range(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):
if not base.cr.isPaid():
if self.velvetRoped():
if hasattr(localAvatar, '_gagTreeVelvetRoped'):
return False
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 range(myLevel):
if levelToTest not in levelsInTrack:
return False
curTree = levelTreeDict[levelToTest]
if not curTree.isGTEFullGrown():
return False
return True
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 velvetRoped(self):
return not base.cr.isPaid() and ToontownBattleGlobals.gagIsPaidOnly(self.gagTrack, self.gagLevel)
def allowedToPick(self):
retval = True
if self.velvetRoped():
retval = False
return retval
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