toontown-just-works/toontown/estate/DistributedGagTree.py

407 lines
15 KiB
Python
Raw Normal View History

2024-07-07 18:08:39 -05:00
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