from panda3d.core import * from toontown.toonbase.ToonBaseGlobal import * from direct.gui.DirectGui import * from direct.distributed.ClockDelta import * from direct.interval.IntervalGlobal import * import math from toontown.toonbase import ToontownGlobals from direct.distributed import DistributedObject from direct.task.Task import Task from toontown.toonbase import TTLocalizer import random import cPickle import time import HouseGlobals from toontown.estate import GardenGlobals from toontown.estate import FlowerSellGUI from toontown.toontowngui import TTDialog from toontown.fishing import FishSellGUI class DistributedEstate(DistributedObject.DistributedObject): notify = directNotify.newCategory('DistributedEstate') def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.closestHouse = 0 self.ground = None self.dayTrack = None self.sunTrack = None self.airplane = None self.flowerSellBox = None self.estateDoneEvent = 'estateDone' self.load() self.initCamera() self.plotTable = [] self.idList = [] self.flowerGuiDoneEvent = 'flowerGuiDone' self.fishGuiDoneEvent = 'fishGuiDone' def disable(self): self.notify.debug('disable') self.__stopBirds() self.__stopCrickets() DistributedObject.DistributedObject.disable(self) self.ignoreAll() def delete(self): self.notify.debug('delete') self.unload() DistributedObject.DistributedObject.delete(self) def load(self): self.defaultSignModel = loader.loadModel('phase_13/models/parties/eventSign') self.activityIconsModel = loader.loadModel('phase_4/models/parties/eventSignIcons') if base.cr.newsManager.isHolidayRunning(ToontownGlobals.HALLOWEEN): self.loadWitch() else: self.loadAirplane() self.loadFlowerSellBox() self.loadFishSellBox() self.oldClear = base.win.getClearColor() base.win.setClearColor(Vec4(0.09, 0.55, 0.21, 1.0)) def unload(self): self.ignoreAll() base.win.setClearColor(self.oldClear) self.__killAirplaneTask() self.__killDaytimeTask() self.__stopBirds() self.__stopCrickets() if self.dayTrack: self.dayTrack.pause() self.dayTrack = None self.__killSunTask() if self.sunTrack: self.sunTrack.pause() self.sunTrack = None if self.ground: self.ground.removeNode() del self.ground if self.airplane: self.airplane.removeNode() del self.airplane self.airplane = None if self.flowerSellBox: self.flowerSellBox.removeNode() del self.flowerSellBox self.flowerSellBox = None if self.fishSellBox: self.fishSellBox.removeNode() del self.fishSellBox self.fishSellBox = None def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) def loadAirplane(self): self.airplane = loader.loadModel('phase_4/models/props/airplane.bam') self.airplane.setScale(4) self.airplane.setPos(0, 0, 1) self.banner = self.airplane.find('**/*banner') bannerText = TextNode('bannerText') bannerText.setTextColor(1, 0, 0, 1) bannerText.setAlign(bannerText.ACenter) bannerText.setFont(ToontownGlobals.getSignFont()) bannerText.setText(TTLocalizer.EstatePlaneReturn) self.bn = self.banner.attachNewNode(bannerText.generate()) self.bn.setHpr(180, 0, 0) self.bn.setPos(-5.8, 0.1, -0.25) self.bn.setScale(0.95) self.bn.setDepthTest(1) self.bn.setDepthWrite(1) self.bn.setDepthOffset(500) def loadWitch(self): if not self.airplane: self.airplane = loader.loadModel('phase_4/models/props/tt_m_prp_ext_flyingWitch.bam') def __replaceAirplane__(): self.airplane.reparentTo(hidden) del self.airplane self.airplane = loader.loadModel('phase_4/models/props/tt_m_prp_ext_flyingWitch.bam') self.airplane.setScale(2) self.airplane.setPos(0, 0, 1) self.airplane.find('**/').setH(180) bannerText = TextNode('bannerText') bannerText.setTextColor(1, 0, 0, 1) bannerText.setAlign(bannerText.ACenter) bannerText.setFont(ToontownGlobals.getSignFont()) bannerText.setText(TTLocalizer.EstatePlaneHoliday) self.bn = self.airplane.attachNewNode(bannerText.generate()) self.bn.setPos(-20.0, -.1, 0) self.bn.setH(180) self.bn.setScale(2.35) self.bn.setDepthTest(1) self.bn.setDepthWrite(1) self.bn.setDepthOffset(500) replacement = Sequence(LerpColorScaleInterval(self.airplane, 0.1, Vec4(1, 1, 1, 0)), Func(__replaceAirplane__), LerpColorScaleInterval(self.airplane, 0.1, Vec4(1, 1, 1, 1))) replacement.start() def unloadWitch(self): def __replaceWitch__(): self.airplane.reparentTo(hidden) del self.airplane del self.bn self.airplane = loader.loadModel('phase_4/models/props/airplane.bam') self.airplane.setScale(4) self.airplane.setPos(0, 0, 1) self.banner = self.airplane.find('**/*banner') bannerText = TextNode('bannerText') bannerText.setTextColor(1, 0, 0, 1) bannerText.setAlign(bannerText.ACenter) bannerText.setFont(ToontownGlobals.getSignFont()) bannerText.setText(TTLocalizer.EstatePlaneReturn) self.bn = self.banner.attachNewNode(bannerText.generate()) self.bn.setHpr(180, 0, 0) self.bn.setPos(-5.8, 0.1, -0.25) self.bn.setScale(0.95) self.bn.setDepthTest(1) self.bn.setDepthWrite(1) self.bn.setDepthOffset(500) replacement = Sequence(LerpColorScaleInterval(self.airplane, 0.1, Vec4(1, 1, 1, 0)), Func(__replaceWitch__), LerpColorScaleInterval(self.airplane, 0.1, Vec4(1, 1, 1, 1))) replacement.start() def initCamera(self): initCamPos = VBase3(0, -10, 5) initCamHpr = VBase3(0, -10, 0) def setEstateType(self, index): self.estateType = index def setHouseInfo(self, houseInfo): self.notify.debug('setHouseInfo') houseType, housePos = cPickle.loads(houseInfo) self.loadEstate(houseType, housePos) def loadEstate(self, indexList, posList): self.notify.debug('loadEstate') self.houseType = indexList self.housePos = posList self.numHouses = len(self.houseType) self.house = [None] * self.numHouses def __startAirplaneTask(self): self.theta = 0 self.phi = 0 taskMgr.remove(self.taskName('estate-airplane')) taskMgr.add(self.airplaneFlyTask, self.taskName('estate-airplane')) def __pauseAirplaneTask(self): pause = 45 self.phi = 0 self.airplane.reparentTo(hidden) self.theta = (self.theta + 10) % 360 taskMgr.remove(self.taskName('estate-airplane')) taskMgr.doMethodLater(pause, self.airplaneFlyTask, self.taskName('estate-airplane')) def __killAirplaneTask(self): taskMgr.remove(self.taskName('estate-airplane')) def airplaneFlyTask(self, task): rad = 300.0 amp = 80.0 self.theta += 0.25 self.phi += 0.005 sinPhi = math.sin(self.phi) if sinPhi <= 0: self.__pauseAirplaneTask() angle = math.pi * self.theta / 180.0 x = rad * math.cos(angle) y = rad * math.sin(angle) z = amp * sinPhi self.airplane.reparentTo(render) self.airplane.setH(90 + self.theta) self.airplane.setPos(x, y, z) return Task.cont def sendHouseColor(self, index, r, g, b, a): self.house[index].setColor(r, g, b, a) def setTreasureIds(self, doIds): self.flyingTreasureId = [] for id in doIds: self.flyingTreasureId.append(id) def setDawnTime(self, ts): self.notify.debug('setDawnTime') self.dawnTime = ts self.sendUpdate('requestServerTime', []) def setServerTime(self, ts): self.notify.debug('setServerTime') self.serverTime = ts self.clientTime = time.time() % HouseGlobals.DAY_NIGHT_PERIOD self.deltaTime = self.clientTime - self.serverTime if base.dayNightEnabled: self.__initDaytimeTask() self.__initSunTask() self.__startAirplaneTask() def getDeltaTime(self): curTime = time.time() % HouseGlobals.DAY_NIGHT_PERIOD dawnTime = self.dawnTime dT = (curTime - dawnTime - self.deltaTime) % HouseGlobals.DAY_NIGHT_PERIOD self.notify.debug( 'getDeltaTime = %s. curTime=%s. dawnTime=%s. serverTime=%s. deltaTime=%s' % (dT, curTime, dawnTime, self.serverTime, self.deltaTime)) return dT def __initDaytimeTask(self): self.__killDaytimeTask() task = Task(self.__dayTimeTask) dT = self.getDeltaTime() task.ts = dT taskMgr.add(task, self.taskName('daytime')) def __killDaytimeTask(self): taskMgr.remove(self.taskName('daytime')) def __dayTimeTask(self, task): taskName = self.taskName('daytime') track = Sequence(Parallel(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, HouseGlobals.HALF_DAY_PERIOD, Vec4(1, 0.6, 0.6, 1)), LerpColorScaleInterval(base.cr.playGame.hood.sky, HouseGlobals.HALF_DAY_PERIOD, Vec4(1, 0.8, 0.8, 1))), Parallel(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, HouseGlobals.HALF_NIGHT_PERIOD, Vec4(0.2, 0.2, 0.5, 1)), LerpColorScaleInterval(base.cr.playGame.hood.sky, HouseGlobals.HALF_NIGHT_PERIOD, Vec4(0.2, 0.2, 0.4, 1))), Parallel(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, HouseGlobals.HALF_NIGHT_PERIOD, Vec4(0.6, 0.6, 0.8, 1)), LerpColorScaleInterval(base.cr.playGame.hood.sky, HouseGlobals.HALF_NIGHT_PERIOD, Vec4(0.5, 0.5, 0.6, 1))), Parallel(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, HouseGlobals.HALF_DAY_PERIOD, Vec4(1, 1, 1, 1)), LerpColorScaleInterval(base.cr.playGame.hood.sky, HouseGlobals.HALF_DAY_PERIOD, Vec4(1, 1, 1, 1))), Func(base.cr.playGame.hood.loader.geom.clearColorScale), Func(base.cr.playGame.hood.sky.clearColorScale)) if self.dayTrack: self.dayTrack.finish() self.dayTrack = track ts = 0 if hasattr(task, 'ts'): ts = task.ts self.dayTrack.start(ts) taskMgr.doMethodLater(HouseGlobals.DAY_NIGHT_PERIOD - ts, self.__dayTimeTask, self.taskName('daytime')) return Task.done def __initSunTask(self): self.__killSunTask() task = Task(self.__sunTask) dT = self.getDeltaTime() task.ts = dT taskMgr.add(task, self.taskName('sunTask')) def __killSunTask(self): taskMgr.remove(self.taskName('sunTask')) def __sunTask(self, task): sunMoonNode = base.cr.playGame.hood.loader.sunMoonNode sun = base.cr.playGame.hood.loader.sun h = 30 halfPeriod = HouseGlobals.DAY_NIGHT_PERIOD / 2.0 track = Sequence(Parallel(LerpHprInterval(sunMoonNode, HouseGlobals.HALF_DAY_PERIOD, Vec3(0, 0, 0)), LerpColorScaleInterval(sun, HouseGlobals.HALF_DAY_PERIOD, Vec4(1, 1, 0.5, 1))), Func(sun.clearColorScale), Func(self.__stopBirds), LerpHprInterval(sunMoonNode, 0.2, Vec3(0, -h - 3, 0)), LerpHprInterval(sunMoonNode, 0.1, Vec3(0, -h + 2, 0)), LerpHprInterval(sunMoonNode, 0.1, Vec3(0, -h - 1.5, 0)), LerpHprInterval(sunMoonNode, 0.1, Vec3(0, -h, 0)), Func(self.notify.debug, 'night'), Wait(HouseGlobals.HALF_NIGHT_PERIOD - 0.5), LerpHprInterval(sunMoonNode, HouseGlobals.HALF_NIGHT_PERIOD, Vec3(0, 0, 0)), Func(self.__startBirds), LerpHprInterval(sunMoonNode, 0.2, Vec3(0, h + 3, 0)), LerpHprInterval(sunMoonNode, 0.1, Vec3(0, h - 2, 0)), LerpHprInterval(sunMoonNode, 0.1, Vec3(0, h + 1.5, 0)), LerpHprInterval(sunMoonNode, 0.1, Vec3(0, h, 0)), Func(self.notify.debug, 'day'), Func(sunMoonNode.setHpr, 0, h, 0), Wait(HouseGlobals.HALF_DAY_PERIOD - 0.5)) if self.sunTrack: self.sunTrack.finish() self.sunTrack = track ts = 0 if hasattr(task, 'ts'): ts = task.ts if ts > HouseGlobals.HALF_DAY_PERIOD and ts < HouseGlobals.DAY_NIGHT_PERIOD - HouseGlobals.HALF_DAY_PERIOD: self.__stopBirds() self.__startCrickets() else: self.__stopCrickets() self.__startBirds() self.sunTrack.start(ts) taskMgr.doMethodLater(HouseGlobals.DAY_NIGHT_PERIOD - ts, self.__sunTask, self.taskName('sunTask')) return Task.done def __stopBirds(self): taskMgr.remove('estate-birds') def __startBirds(self): self.__stopBirds() taskMgr.doMethodLater(1, self.__birds, 'estate-birds') def __birds(self, task): base.playSfx(random.choice(base.cr.playGame.hood.loader.birdSound)) t = random.random() * 20.0 + 1 taskMgr.doMethodLater(t, self.__birds, 'estate-birds') return Task.done def __stopCrickets(self): taskMgr.remove('estate-crickets') def __startCrickets(self): self.__stopCrickets() taskMgr.doMethodLater(1, self.__crickets, 'estate-crickets') def __crickets(self, task): sfx = base.cr.playGame.hood.loader.cricketSound track = Sequence(Func(base.playSfx, random.choice(sfx)), Wait(1)) track.start() t = random.random() * 20.0 + 1 taskMgr.doMethodLater(t, self.__crickets, 'estate-crickets') return Task.done def getLastEpochTimeStamp(self): return self.lastEpochTimeStamp def setLastEpochTimeStamp(self, ts): self.lastEpochTimeStamp = ts def getIdList(self): return self.idList def setIdList(self, idList): self.idList = idList def loadFlowerSellBox(self): self.flowerSellBox = loader.loadModel('phase_5.5/models/estate/wheelbarrel.bam') self.flowerSellBox.setPos(-142.586, 4.353, 0.025) self.flowerSellBox.reparentTo(render) colNode = self.flowerSellBox.find('**/collision') colNode.setName('FlowerSellBox') self.accept('enterFlowerSellBox', self.__touchedFlowerSellBox) def __touchedFlowerSellBox(self, entry): if base.localAvatar.doId in self.idList: if len(base.localAvatar.flowerBasket.flowerList): self.popupFlowerGUI() def __handleSaleDone(self, sell = 0): self.ignore(self.flowerGuiDoneEvent) self.sendUpdate('completeFlowerSale', [sell]) self.ignore('stoppedAsleep') self.flowerGui.destroy() self.flowerGui = None def popupFlowerGUI(self): self.acceptOnce(self.flowerGuiDoneEvent, self.__handleSaleDone) self.flowerGui = FlowerSellGUI.FlowerSellGUI(self.flowerGuiDoneEvent) self.accept('stoppedAsleep', self.__handleSaleDone) def loadFishSellBox(self): self.fishSellBox = loader.loadModel('phase_4/models/minigames/treasure_chest.bam') self.fishSellBox.setPos(45, -165.75, 0.025) self.fishSellBox.setH(210) self.fishSellBox.reparentTo(render) cSphere = CollisionSphere(0.0, 0.0, 0.0, 2.25) cSphere.setTangible(0) colNode = CollisionNode('FishSellBox') colNode.addSolid(cSphere) cSpherePath = self.fishSellBox.attachNewNode(colNode) cSpherePath.hide() cSpherePath.setCollideMask(ToontownGlobals.WallBitmask) self.accept('enterFishSellBox', self.__touchedFishSellBox) def __touchedFishSellBox(self, entry): if base.localAvatar.doId in self.idList: if base.localAvatar.fishTank.getFish(): self.popupFishGUI() def __handleFishSaleDone(self, sell=0): if sell: self.sendUpdate('completeFishSale') else: base.localAvatar.setSystemMessage(0, TTLocalizer.STOREOWNER_NOFISH) base.setCellsAvailable(base.bottomCells, 1) base.cr.playGame.getPlace().setState('walk') self.ignore(self.fishGuiDoneEvent) self.ignore('stoppedAsleep') self.fishGui.destroy() self.fishGui = None def popupFishGUI(self): base.setCellsAvailable(base.bottomCells, 0) base.cr.playGame.getPlace().setState('stopped') self.acceptOnce(self.fishGuiDoneEvent, self.__handleFishSaleDone) self.fishGui = FishSellGUI.FishSellGUI(self.fishGuiDoneEvent) self.accept('stoppedAsleep', self.__handleFishSaleDone) def thankSeller(self, mode, fish, maxFish): if mode == ToontownGlobals.FISHSALE_TROPHY: base.localAvatar.setSystemMessage(0, TTLocalizer.STOREOWNER_TROPHY % (fish, maxFish)) elif mode == ToontownGlobals.FISHSALE_COMPLETE: base.localAvatar.setSystemMessage(0, TTLocalizer.STOREOWNER_THANKSFISH) def closedAwardDialog(self, value): self.awardDialog.destroy() base.cr.playGame.getPlace().detectedGardenPlotDone() def awardedTrophy(self, avId): if base.localAvatar.doId == avId: base.cr.playGame.getPlace().detectedGardenPlotUse() msg = TTLocalizer.GardenTrophyAwarded % (len(base.localAvatar.getFlowerCollection()), GardenGlobals.getNumberOfFlowerVarieties()) self.awardDialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=msg, command=self.closedAwardDialog) def setClouds(self, clouds): self.clouds = clouds base.cr.playGame.hood.loader.setCloudSwitch(clouds) def getClouds(self): if hasattr(self, 'clouds'): return self.clouds else: return 0 def cannonsOver(self, arg = None): base.localAvatar.setSystemMessage(0, TTLocalizer.EstateCannonGameEnd) def gameTableOver(self, arg = None): base.localAvatar.setSystemMessage(0, TTLocalizer.GameTableRentalEnd)