from panda3d.core import * from direct.interval.IntervalGlobal import * from direct.gui.DirectGui import * from direct.directtools.DirectGeometry import LineNodePath from direct.distributed import DistributedObject from direct.directnotify import DirectNotifyGlobal from toontown.toonbase import ToontownGlobals from toontown.fishing import FishGlobals from toontown.shtiker import FishPage from toontown.toonbase import TTLocalizer from toontown.quest import Quests from direct.actor import Actor from direct.showutil import Rope import math from direct.task.Task import Task import random import random from toontown.fishing import FishingTargetGlobals from toontown.fishing import FishBase from toontown.fishing import FishPanel from toontown.effects import Ripples from toontown.toontowngui import TTDialog from toontown.toonbase import ToontownTimer from direct.fsm import ClassicFSM, State from direct.fsm import State from toontown.hood import ZoneUtil from toontown.toontowngui import TeaserPanel class DistributedFishingSpot(DistributedObject.DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedFishingSpot') vZeroMax = 25.0 angleMax = 30.0 def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.lastAvId = 0 self.lastFrame = 0 self.avId = 0 self.av = None self.placedAvatar = 0 self.localToonFishing = 0 self.nodePath = None self.collSphere = None self.collNode = None self.collNodePath = None self.castTrack = None self.pondDoId = None self.pond = None self.guiTrack = None self.madeGui = 0 self.castGui = None self.itemGui = None self.pole = None self.line = None self.poleNode = [] self.ptop = None self.bob = None self.bobBobTask = None self.splashSounds = None self.ripples = None self.line = None self.lineSphere = None self.power = 0.0 self.startAngleNP = 0 self.firstCast = 1 self.fishPanel = None self.fsm = ClassicFSM.ClassicFSM('DistributedFishingSpot', [State.State('off', self.enterOff, self.exitOff, ['waiting', 'distCasting', 'fishing', 'reward', 'leaving']), State.State('waiting', self.enterWaiting, self.exitWaiting, ['localAdjusting', 'distCasting', 'leaving', 'sellFish']), State.State('localAdjusting', self.enterLocalAdjusting, self.exitLocalAdjusting, ['localCasting', 'leaving']), State.State('localCasting', self.enterLocalCasting, self.exitLocalCasting, ['localAdjusting', 'fishing', 'leaving']), State.State('distCasting', self.enterDistCasting, self.exitDistCasting, ['fishing', 'leaving', 'reward']), State.State('fishing', self.enterFishing, self.exitFishing, ['localAdjusting', 'distCasting', 'waitForAI', 'reward', 'leaving']), State.State('sellFish', self.enterSellFish, self.exitSellFish, ['waiting', 'leaving']), State.State('waitForAI', self.enterWaitForAI, self.exitWaitForAI, ['reward', 'leaving']), State.State('reward', self.enterReward, self.exitReward, ['localAdjusting', 'distCasting', 'leaving', 'sellFish']), State.State('leaving', self.enterLeaving, self.exitLeaving, [])], 'off', 'off') self.fsm.enterInitialState() return def disable(self): self.ignore(self.uniqueName('enterFishingSpotSphere')) self.setOccupied(0) self.avId = 0 if self.castTrack != None: if self.castTrack.isPlaying(): self.castTrack.finish() self.castTrack = None if self.guiTrack != None: if self.guiTrack.isPlaying(): self.guiTrack.finish() self.guiTrack = None self.__hideBob() self.nodePath.detachNode() self.__unmakeGui() self.pond.stopCheckingTargets() self.pond = None self.pondDoId = None DistributedObject.DistributedObject.disable(self) return def delete(self): del self.pond del self.pondDoId del self.fsm if self.nodePath: self.nodePath.removeNode() del self.nodePath DistributedObject.DistributedObject.delete(self) if self.ripples: self.ripples.destroy() def generateInit(self): DistributedObject.DistributedObject.generateInit(self) self.nodePath = NodePath(self.uniqueName('FishingSpot')) self.angleNP = self.nodePath.attachNewNode(self.uniqueName('FishingSpotAngleNP')) self.collSphere = CollisionSphere(0, 0, 0, self.getSphereRadius()) self.collSphere.setTangible(0) self.collNode = CollisionNode(self.uniqueName('FishingSpotSphere')) self.collNode.setCollideMask(ToontownGlobals.WallBitmask) self.collNode.addSolid(self.collSphere) self.collNodePath = self.nodePath.attachNewNode(self.collNode) self.bobStartPos = Point3(0.0, 3.0, 8.5) def generate(self): DistributedObject.DistributedObject.generate(self) def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) self.nodePath.reparentTo(self.getParentNodePath()) self.accept(self.uniqueName('enterFishingSpotSphere'), self.__handleEnterSphere) def setPondDoId(self, pondDoId): self.pondDoId = pondDoId if self.pondDoId in self.cr.doId2do: self.setPond(self.cr.doId2do[self.pondDoId]) else: self.acceptOnce('generate-%s' % self.pondDoId, self.setPond) def setPond(self, pond): self.pond = pond self.area = self.pond.getArea() self.waterLevel = FishingTargetGlobals.getWaterLevel(self.area) def allowedToEnter(self): if hasattr(base, 'ttAccess') and base.ttAccess and base.ttAccess.canAccess(): return True return False def handleOkTeaser(self): self.dialog.destroy() del self.dialog place = base.cr.playGame.getPlace() if place: place.fsm.request('walk') def __handleEnterSphere(self, collEntry): if self.allowedToEnter(): if base.localAvatar.doId == self.lastAvId and globalClock.getFrameCount() <= self.lastFrame + 1: self.notify.debug('Ignoring duplicate entry for avatar.') return if base.localAvatar.hp > 0 and base.cr.playGame.getPlace().fsm.getCurrentState().getName() != 'fishing': self.cr.playGame.getPlace().detectedFishingCollision() self.d_requestEnter() else: place = base.cr.playGame.getPlace() if place: place.fsm.request('stopped') self.dialog = TeaserPanel.TeaserPanel(pageName='fishing', doneFunc=self.handleOkTeaser) def d_requestEnter(self): self.sendUpdate('requestEnter', []) def rejectEnter(self): self.cr.playGame.getPlace().setState('walk') def d_requestExit(self): self.sendUpdate('requestExit', []) def d_doCast(self, power, heading): self.sendUpdate('doCast', [power, heading]) def getSphereRadius(self): return 1.5 def getParentNodePath(self): return render def setPosHpr(self, x, y, z, h, p, r): self.nodePath.setPosHpr(x, y, z, h, p, r) self.angleNP.setH(render, self.nodePath.getH(render)) def setOccupied(self, avId): if self.av != None: if not self.av.isEmpty(): self.__dropPole() self.av.loop('neutral') self.av.setParent(ToontownGlobals.SPRender) self.av.startSmooth() self.ignore(self.av.uniqueName('disable')) self.__hideBob() self.fsm.requestFinalState() self.__removePole() self.av = None self.placedAvatar = 0 self.angleNP.setH(render, self.nodePath.getH(render)) self.__hideLine() wasLocalToon = self.localToonFishing self.lastAvId = self.avId self.lastFrame = globalClock.getFrameCount() self.avId = avId self.localToonFishing = 0 if self.avId == 0: self.collSphere.setTangible(0) else: self.collSphere.setTangible(1) if self.avId == base.localAvatar.doId: base.setCellsAvailable(base.bottomCells, 0) self.localToonFishing = 1 if base.wantBingo: self.pond.setLocalToonSpot(self) av = self.cr.doId2do.get(self.avId) if av: self.av = av self.__loadStuff() self.placedAvatar = 0 self.firstCast = 1 self.acceptOnce(self.av.uniqueName('disable'), self.__avatarGone) self.av.stopSmooth() self.av.wrtReparentTo(self.angleNP) self.av.setAnimState('neutral', 1.0) self.createCastTrack() else: self.notify.warning('Unknown avatar %d in fishing spot %d' % (self.avId, self.doId)) if wasLocalToon and not self.localToonFishing: self.__hideCastGui() if base.wantBingo: self.pond.setLocalToonSpot() base.setCellsAvailable([base.bottomCells[1], base.bottomCells[2]], 1) base.setCellsAvailable(base.rightCells, 1) place = base.cr.playGame.getPlace() if place: place.setState('walk') return def __avatarGone(self): self.setOccupied(0) def setMovie(self, mode, code, itemDesc1, itemDesc2, itemDesc3, power, h): if self.av == None: return if mode == FishGlobals.NoMovie: pass elif mode == FishGlobals.EnterMovie: self.fsm.request('waiting') elif mode == FishGlobals.ExitMovie: self.fsm.request('leaving') elif mode == FishGlobals.CastMovie: if not self.localToonFishing: self.fsm.request('distCasting', [power, h]) elif mode == FishGlobals.PullInMovie: self.fsm.request('reward', [code, itemDesc1, itemDesc2, itemDesc3]) return def getStareAtNodeAndOffset(self): return (self.nodePath, Point3()) def __loadStuff(self): rodId = self.av.getFishingRod() rodPath = FishGlobals.RodFileDict.get(rodId) if not rodPath: self.notify.warning('Rod id: %s model not found' % rodId) rodPath = RodFileDict[0] self.pole = Actor.Actor() self.pole.loadModel(rodPath) self.pole.loadAnims({'cast': 'phase_4/models/props/fishing-pole-chan'}) self.pole.pose('cast', 0) self.ptop = self.pole.find('**/joint_attachBill') if self.line == None: self.line = Rope.Rope(self.uniqueName('Line')) self.line.setColor(1, 1, 1, 0.4) self.line.setTransparency(1) self.lineSphere = BoundingSphere(Point3(-0.6, -2, -5), 5.5) if self.bob == None: self.bob = loader.loadModel('phase_4/models/props/fishing_bob') self.bob.setScale(1.5) self.ripples = Ripples.Ripples(self.nodePath) self.ripples.setScale(0.4) self.ripples.hide() if self.splashSounds == None: self.splashSounds = (base.loader.loadSfx('phase_4/audio/sfx/TT_splash1.ogg'), base.loader.loadSfx('phase_4/audio/sfx/TT_splash2.ogg')) return def __placeAvatar(self): if not self.placedAvatar: self.placedAvatar = 1 self.__holdPole() self.av.setPosHpr(0, 0, 0, 0, 0, 0) def __holdPole(self): if self.poleNode != []: self.__dropPole() np = NodePath('pole-holder') hands = self.av.getRightHands() for h in hands: self.poleNode.append(np.instanceTo(h)) self.pole.reparentTo(self.poleNode[0]) def __dropPole(self): self.__hideBob() self.__hideLine() if self.pole != None: self.pole.clearMat() self.pole.detachNode() for pn in self.poleNode: pn.removeNode() self.poleNode = [] return def __removePole(self): self.pole.removeNode() self.poleNode = [] self.ptop.removeNode() self.pole = None self.ptop = None return def __showLineWaiting(self): self.line.setup(4, ((None, (0, 0, 0)), (None, (0, -2, -4)), (self.bob, (0, -1, 0)), (self.bob, (0, 0, 0)))) self.line.ropeNode.setBounds(self.lineSphere) self.line.reparentTo(self.ptop) return def __showLineCasting(self): self.line.setup(2, ((None, (0, 0, 0)), (self.bob, (0, 0, 0)))) self.line.ropeNode.setBounds(self.lineSphere) self.line.reparentTo(self.ptop) return def __showLineReeling(self): self.line.setup(2, ((None, (0, 0, 0)), (self.bob, (0, 0, 0)))) self.line.ropeNode.setBounds(self.lineSphere) self.line.reparentTo(self.ptop) return def __hideLine(self): if self.line: self.line.detachNode() def __showBobFloat(self): self.__hideBob() self.bob.reparentTo(self.angleNP) self.ripples.reparentTo(self.angleNP) self.ripples.setPos(self.bob.getPos()) self.ripples.setZ(self.waterLevel + 0.025) self.ripples.play() splashSound = random.choice(self.splashSounds) base.playSfx(splashSound, volume=0.8, node=self.bob) self.bobBobTask = taskMgr.add(self.__doBobBob, self.taskName('bob')) def __hideBob(self): if self.bob: self.bob.detachNode() if self.bobBobTask: taskMgr.remove(self.bobBobTask) self.bobBobTask = None if self.ripples: self.ripples.stop() self.ripples.detachNode() return def __doBobBob(self, task): z = math.sin(task.time * 1.8) * 0.08 self.bob.setZ(self.waterLevel + z) return Task.cont def __userExit(self, event = None): if self.localToonFishing: self.fsm.request('leaving') self.d_requestExit() def __sellFish(self, result = None): if self.localToonFishing: if result == DGG.DIALOG_OK: self.sendUpdate('sellFish', []) for button in self.sellFishDialog.buttonList: button['state'] = DGG.DISABLED else: self.fsm.request('leaving') self.d_requestExit() def __sellFishConfirm(self, result = None): if self.localToonFishing: self.fsm.request('waiting', [False]) def __showCastGui(self): self.__hideCastGui() self.__makeGui() self.castButton.show() self.arrow.hide() self.exitButton.show() self.timer.show() self.__updateFishTankGui() self.castGui.reparentTo(base.a2dBottomCenterNs) self.castButton['state'] = DGG.NORMAL self.jar['text'] = str(self.av.getMoney()) self.accept(localAvatar.uniqueName('moneyChange'), self.__moneyChange) self.accept(localAvatar.uniqueName('fishTankChange'), self.__updateFishTankGui) target = base.cr.doFind('DistributedTarget') if target: target.hideGui() if base.wantBingo: self.__setBingoCastGui() def requestLocalAdjusting(mouseEvent): if self.av.isFishTankFull() and self.__allowSellFish(): self.fsm.request('sellFish') else: self.fsm.request('localAdjusting') def requestLocalCasting(mouseEvent): if not (self.av.isFishTankFull() and self.__allowSellFish()): self.fsm.request('localCasting') self.castButton.bind(DGG.B1PRESS, requestLocalAdjusting) self.castButton.bind(DGG.B3PRESS, requestLocalAdjusting) self.castButton.bind(DGG.B1RELEASE, requestLocalCasting) self.castButton.bind(DGG.B3RELEASE, requestLocalCasting) if self.firstCast and len(self.av.fishCollection) == 0 and len(self.av.fishTank) == 0: self.__showHowTo(TTLocalizer.FishingHowToFirstTime) elif base.wantBingo and self.pond.hasPondBingoManager() and not self.av.bFishBingoTutorialDone: self.__showHowTo(TTLocalizer.FishBingoHelpMain) self.av.b_setFishBingoTutorialDone(True) def __moneyChange(self, money): self.jar['text'] = str(money) def __initCastGui(self): self.timer.countdown(FishGlobals.CastTimeout) def __showQuestItem(self, itemId): self.__makeGui() itemName = Quests.getItemName(itemId) self.itemLabel['text'] = itemName self.itemGui.reparentTo(aspect2d) self.itemPackage.show() self.itemJellybean.hide() self.itemBoot.hide() def __showBootItem(self): self.__makeGui() itemName = TTLocalizer.FishingBootItem self.itemLabel['text'] = itemName self.itemGui.reparentTo(aspect2d) self.itemBoot.show() self.itemJellybean.hide() self.itemPackage.hide() def __setItemLabel(self): if self.pond.hasPondBingoManager(): self.itemLabel['text'] = str(itemName + '\n\n' + 'BINGO WILDCARD') else: self.itemLabel['text'] = itemName def __showJellybeanItem(self, amount): self.__makeGui() itemName = TTLocalizer.FishingJellybeanItem % amount self.itemLabel['text'] = itemName self.itemGui.reparentTo(aspect2d) self.jar['text'] = str(self.av.getMoney()) self.itemJellybean.show() self.itemBoot.hide() self.itemPackage.hide() def __showFishItem(self, code, fish): self.fishPanel = FishPanel.FishPanel(fish) self.__setFishItemPos() self.fishPanel.setSwimBounds(-0.3, 0.3, -0.235, 0.25) self.fishPanel.setSwimColor(1.0, 1.0, 0.74901, 1.0) self.fishPanel.load() self.fishPanel.show(code) self.__updateFishTankGui() def __setFishItemPos(self): if base.wantBingo: if self.pond.hasPondBingoManager(): self.fishPanel.setPos(0.65, 0, 0.4) else: self.fishPanel.setPos(0, 0, 0.5) else: self.fishPanel.setPos(0, 0, 0.5) def __updateFishTankGui(self): fishTank = self.av.getFishTank() lenFishTank = len(fishTank) maxFishTank = self.av.getMaxFishTank() self.bucket['text'] = '%s/%s' % (lenFishTank, maxFishTank) def __showFailureReason(self, code): self.__makeGui() reason = '' if code == FishGlobals.OverTankLimit: reason = TTLocalizer.FishingOverTankLimit self.failureDialog.setMessage(reason) self.failureDialog.show() def __showSellFishDialog(self): self.__makeGui() self.sellFishDialog.show() def __hideSellFishDialog(self): self.__makeGui() self.sellFishDialog.hide() def __showSellFishConfirmDialog(self, numFishCaught): self.__makeGui() msg = TTLocalizer.STOREOWNER_TROPHY % (numFishCaught, FishGlobals.getTotalNumFish()) self.sellFishConfirmDialog.setMessage(msg) self.sellFishConfirmDialog.show() def __hideSellFishConfirmDialog(self): self.__makeGui() self.sellFishConfirmDialog.hide() def __showBroke(self): self.__makeGui() self.brokeDialog.show() self.castButton['state'] = DGG.DISABLED def __showHowTo(self, message): self.__makeGui() self.howToDialog.setMessage(message) self.howToDialog.show() def __hideHowTo(self, event = None): self.__makeGui() self.howToDialog.hide() def __showFishTankFull(self): self.__makeGui() self.__showFailureReason(FishGlobals.OverTankLimit) self.castButton['state'] = DGG.DISABLED def __hideCastGui(self): target = base.cr.doFind('DistributedTarget') if target: target.showGui() if self.madeGui: self.timer.hide() self.castGui.detachNode() self.itemGui.detachNode() self.failureDialog.hide() self.sellFishDialog.hide() self.sellFishConfirmDialog.hide() self.brokeDialog.hide() self.howToDialog.hide() self.castButton.unbind(DGG.B1PRESS) self.castButton.unbind(DGG.B3PRESS) self.castButton.unbind(DGG.B1RELEASE) self.castButton.unbind(DGG.B3RELEASE) self.ignore(localAvatar.uniqueName('moneyChange')) self.ignore(localAvatar.uniqueName('fishTankChange')) def __itemGuiClose(self): self.itemGui.detachNode() def __makeGui(self): if base.config.GetBool('want-qa-regression', 0): self.notify.info('QA-REGRESSION: FISHING: ZoneId: %s' % self.pond.getArea()) if self.madeGui: return self.timer = ToontownTimer.ToontownTimer() self.timer.posInTopRightCorner() self.timer.hide() self.castGui = loader.loadModel('phase_4/models/gui/fishingGui') self.castGui.setScale(0.67) self.castGui.setPos(0, 0, 1) for nodeName in ('bucket', 'jar', 'display_bucket', 'display_jar'): self.castGui.find('**/' + nodeName).reparentTo(self.castGui) self.castGui.find('**/boards').setScale(2, 1, 1) self.exitButton = DirectButton(parent=self.castGui, relief=None, text=('', TTLocalizer.FishingExit, TTLocalizer.FishingExit), text_align=TextNode.ACenter, text_scale=0.1, text_fg=Vec4(1, 1, 1, 1), text_shadow=Vec4(0, 0, 0, 1), text_pos=(0.0, -0.12), pos=(1.75, 0, -1.33), textMayChange=0, image=(self.castGui.find('**/exit_buttonUp'), self.castGui.find('**/exit_buttonDown'), self.castGui.find('**/exit_buttonRollover')), command=self.__userExit) self.castGui.find('**/exitButton').removeNode() self.castButton = DirectButton(parent=self.castGui, relief=None, text=TTLocalizer.FishingCast, text_align=TextNode.ACenter, text_scale=(3, 3 * 0.75, 3 * 0.75), text_fg=Vec4(1, 1, 1, 1), text_shadow=Vec4(0, 0, 0, 1), text_pos=(0, -4), image=self.castGui.find('**/castButton'), image0_color=(1, 0, 0, 1), image1_color=(0, 1, 0, 1), image2_color=(1, 1, 0, 1), image3_color=(0.8, 0.5, 0.5, 1), pos=(0, -0.05, -0.666), scale=(0.036, 1, 0.048)) self.castGui.find('**/castButton').removeNode() self.arrow = self.castGui.find('**/arrow') self.arrowTip = self.arrow.find('**/arrowTip') self.arrowTail = self.arrow.find('**/arrowTail') self.arrow.reparentTo(self.castGui) self.arrow.setColorScale(0.9, 0.9, 0.1, 0.7) self.arrow.hide() self.jar = DirectLabel(parent=self.castGui, relief=None, text=str(self.av.getMoney()), text_scale=0.16, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont(), pos=(-1.12, 0, -1.3)) self.bucket = DirectLabel(parent=self.castGui, relief=None, text='', text_scale=0.09, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1), pos=(1.14, 0, -1.33)) self.__updateFishTankGui() self.itemGui = NodePath('itemGui') self.itemFrame = DirectFrame(parent=self.itemGui, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=ToontownGlobals.GlobalDialogColor, geom_scale=(1, 1, 0.6), text=TTLocalizer.FishingItemFound, text_pos=(0, 0.2), text_scale=0.08, pos=(0, 0, 0.587)) self.itemLabel = DirectLabel(parent=self.itemFrame, text='', text_scale=0.06, pos=(0, 0, -0.25)) buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') self.itemGuiCloseButton = DirectButton(parent=self.itemFrame, pos=(0.44, 0, -0.24), relief=None, image=(buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr')), image_scale=(0.7, 1, 0.7), command=self.__itemGuiClose) buttons.removeNode() jarGui = loader.loadModel('phase_3.5/models/gui/jar_gui') bootGui = loader.loadModel('phase_4/models/gui/fishing_boot') packageGui = loader.loadModel('phase_3.5/models/gui/stickerbook_gui').find('**/package') self.itemJellybean = DirectFrame(parent=self.itemFrame, relief=None, image=jarGui, scale=0.5) self.itemBoot = DirectFrame(parent=self.itemFrame, relief=None, image=bootGui, scale=0.2) self.itemPackage = DirectFrame(parent=self.itemFrame, relief=None, image=packageGui, scale=0.25) self.itemJellybean.hide() self.itemBoot.hide() self.itemPackage.hide() self.failureDialog = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('failureDialog'), doneEvent=self.uniqueName('failureDialog'), command=self.__userExit, message=TTLocalizer.FishingFailure, style=TTDialog.CancelOnly, cancelButtonText=TTLocalizer.FishingExit) self.failureDialog.hide() self.sellFishDialog = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('sellFishDialog'), doneEvent=self.uniqueName('sellFishDialog'), command=self.__sellFish, message=TTLocalizer.FishBingoOfferToSellFish, style=TTDialog.YesNo) self.sellFishDialog.hide() self.sellFishConfirmDialog = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('sellFishConfirmDialog'), doneEvent=self.uniqueName('sellFishConfirmDialog'), command=self.__sellFishConfirm, message=TTLocalizer.STOREOWNER_TROPHY, style=TTDialog.Acknowledge) self.sellFishConfirmDialog.hide() self.brokeDialog = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('brokeDialog'), doneEvent=self.uniqueName('brokeDialog'), command=self.__userExit, message=TTLocalizer.FishingBroke, style=TTDialog.CancelOnly, cancelButtonText=TTLocalizer.FishingExit) self.brokeDialog.hide() self.howToDialog = TTDialog.TTGlobalDialog(dialogName=self.uniqueName('howToDialog'), doneEvent=self.uniqueName('howToDialog'), fadeScreen=0, message=TTLocalizer.FishingHowToFailed, style=TTDialog.Acknowledge) self.howToDialog['command'] = self.__hideHowTo self.howToDialog.setPos(-0.3, 0, 0.5) self.howToDialog.hide() self.madeGui = 1 return def __setBingoCastGui(self): if self.pond.hasPondBingoManager(): self.notify.debug('__setBingoCastGui: Has PondBing Manager %s' % self.pond.getPondBingoManager().getDoId()) bucket = self.castGui.find('**/bucket') self.castGui.find('**/display_bucket').reparentTo(bucket) self.bucket.reparentTo(bucket) jar = self.castGui.find('**/jar') self.castGui.find('**/display_jar').reparentTo(jar) self.jar.reparentTo(jar) base.setCellsAvailable(base.rightCells, 0) bucket.setScale(0.9) bucket.setX(-1.9) bucket.setZ(-.11) jar.setScale(0.9) jar.setX(-.375) jar.setZ(-.135) else: self.notify.debug('__setItemFramePos: Has No Pond Bingo Manager') bucket = self.castGui.find('**/bucket') bucket.setScale(1) bucket.setPos(0, 0, 0) jar = self.castGui.find('**/jar') jar.setScale(1) jar.setPos(0, 0, 0) def resetCastGui(self): self.notify.debug('resetCastGui: Bingo Night Ends - resetting Gui') bucket = self.castGui.find('**/bucket') jar = self.castGui.find('**/jar') bucketPosInt = bucket.posInterval(5.0, Point3(0, 0, 0), startPos=bucket.getPos(), blendType='easeInOut') bucketScaleInt = bucket.scaleInterval(5.0, VBase3(1.0, 1.0, 1.0), startScale=bucket.getScale(), blendType='easeInOut') bucketTrack = Parallel(bucketPosInt, bucketScaleInt) jarPosInt = jar.posInterval(5.0, Point3(0, 0, 0), startPos=jar.getPos(), blendType='easeInOut') jarScaleInt = jar.scaleInterval(5.0, VBase3(1.0, 1.0, 1.0), startScale=jar.getScale(), blendType='easeInOut') jarTrack = Parallel(jarPosInt, jarScaleInt) self.guiTrack = Parallel(bucketTrack, jarTrack) self.guiTrack.start() def setCastGui(self): self.notify.debug('setCastGui: Bingo Night Starts - setting Gui') bucket = self.castGui.find('**/bucket') self.castGui.find('**/display_bucket').reparentTo(bucket) self.bucket.reparentTo(bucket) jar = self.castGui.find('**/jar') self.castGui.find('**/display_jar').reparentTo(jar) self.jar.reparentTo(jar) bucketPosInt = bucket.posInterval(3.0, Point3(-1.9, 0, -.11), startPos=bucket.getPos(), blendType='easeInOut') bucketScaleInt = bucket.scaleInterval(3.0, VBase3(0.9, 0.9, 0.9), startScale=bucket.getScale(), blendType='easeInOut') bucketTrack = Parallel(bucketPosInt, bucketScaleInt) jarPosInt = jar.posInterval(3.0, Point3(-.375, 0, -.135), startPos=jar.getPos(), blendType='easeInOut') jarScaleInt = jar.scaleInterval(3.0, VBase3(0.9, 0.9, 0.9), startScale=jar.getScale(), blendType='easeInOut') jarTrack = Parallel(jarPosInt, jarScaleInt) self.guiTrack = Parallel(bucketTrack, jarTrack) self.guiTrack.start() def setJarAmount(self, amount): if self.madeGui: money = int(self.jar['text']) + amount pocketMoney = min(money, self.av.getMaxMoney()) self.jar.setProp('text', str(pocketMoney)) def __unmakeGui(self): if not self.madeGui: return self.timer.destroy() del self.timer self.exitButton.destroy() self.castButton.destroy() self.jar.destroy() self.bucket.destroy() self.itemFrame.destroy() self.itemGui.removeNode() self.failureDialog.cleanup() self.sellFishDialog.cleanup() self.sellFishConfirmDialog.cleanup() self.brokeDialog.cleanup() self.howToDialog.cleanup() self.castGui.removeNode() self.madeGui = 0 def localAdjustingCastTask(self, state): self.getMouse() deltaX = self.mouseX - self.initMouseX deltaY = self.mouseY - self.initMouseY if deltaY >= 0: if self.power == 0: self.arrowTail.setScale(0.075, 0.075, 0) self.arrow.setR(0) self.castTrack.pause() return Task.cont dist = math.sqrt(deltaX * deltaX + deltaY * deltaY) delta = dist / 0.5 self.power = max(min(abs(delta), 1.0), 0.0) self.castTrack.setT(0.2 + self.power * 0.7) angle = rad2Deg(math.atan(deltaX / deltaY)) if self.power < 0.25: angle = angle * math.pow(self.power * 4, 3) if delta < 0: angle += 180 minAngle = -FishGlobals.FishingAngleMax maxAngle = FishGlobals.FishingAngleMax if angle < minAngle: self.arrow.setColorScale(1, 0, 0, 1) angle = minAngle elif angle > maxAngle: self.arrow.setColorScale(1, 0, 0, 1) angle = maxAngle else: self.arrow.setColorScale(1, 1 - math.pow(self.power, 3), 0.1, 0.7) self.arrowTail.setScale(0.075, 0.075, self.power * 0.2) self.arrow.setR(angle) self.angleNP.setH(-angle) return Task.cont def localAdjustingCastTaskIndAxes(self, state): self.getMouse() deltaX = self.mouseX - self.initMouseX deltaY = self.mouseY - self.initMouseY self.power = max(min(abs(deltaY) * 1.5, 1.0), 0.0) self.castTrack.setT(0.4 + self.power * 0.5) angle = deltaX * -180.0 self.angleNP.setH(self.startAngleNP - angle) return Task.cont def getMouse(self): if base.mouseWatcherNode.hasMouse(): self.mouseX = base.mouseWatcherNode.getMouseX() self.mouseY = base.mouseWatcherNode.getMouseY() else: self.mouseX = 0 self.mouseY = 0 def createCastTrack(self): self.castTrack = Sequence(ActorInterval(self.av, 'castlong', playRate=4), ActorInterval(self.av, 'cast', startFrame=20), Func(self.av.loop, 'fish-neutral')) def startMoveBobTask(self): self.__showBob() taskMgr.add(self.moveBobTask, self.taskName('moveBobTask')) def moveBobTask(self, task): g = 32.2 t = task.time vZero = self.power * self.vZeroMax angle = deg2Rad(self.power * self.angleMax) deltaY = vZero * math.cos(angle) * t deltaZ = vZero * math.sin(angle) * t - g * t * t / 2.0 deltaPos = Point3(0, deltaY, deltaZ) self.bobStartPos = Point3(0.0, 3.0, 8.5) pos = self.bobStartPos + deltaPos self.bob.setPos(pos) if pos[2] < self.waterLevel: self.fsm.request('fishing') return Task.done else: return Task.cont def __showBob(self): self.__hideBob() self.bob.reparentTo(self.angleNP) self.bob.setPos(self.ptop, 0, 0, 0) self.av.update(0) def hitTarget(self): self.fsm.request('waitForAI') def enterOff(self): pass def exitOff(self): pass def enterWaiting(self, doAnimation = True): self.av.stopLookAround() self.__hideLine() self.track = Parallel() if doAnimation: toonTrack = Sequence(Func(self.av.setPlayRate, 1.0, 'run'), Func(self.av.loop, 'run'), LerpPosHprInterval(self.av, 1.0, Point3(0, 0, 0), Point3(0, 0, 0)), Func(self.__placeAvatar), Parallel(ActorInterval(self.av, 'pole'), Func(self.pole.pose, 'cast', 0), LerpScaleInterval(self.pole, duration=0.5, scale=1.0, startScale=0.01)), Func(self.av.loop, 'pole-neutral')) if self.localToonFishing: camera.wrtReparentTo(render) self.track.append(LerpPosHprInterval(nodePath=camera, other=self.av, duration=1.5, pos=Point3(0, -12, 15), hpr=VBase3(0, -38, 0), blendType='easeInOut')) toonTrack.append(Func(self.__showCastGui)) toonTrack.append(Func(self.__initCastGui)) if base.wantBingo: self.__appendBingoMethod(toonTrack, self.pond.showBingoGui) self.track.append(toonTrack) else: self.__showCastGui() self.track.start() def __appendBingoMethod(self, interval, callback): interval.append(Func(callback)) def exitWaiting(self): self.track.finish() self.track = None return def enterLocalAdjusting(self, guiEvent = None): if self.track: self.track.pause() if self.castTrack: self.castTrack.pause() self.power = 0.0 self.firstCast = 0 self.castButton['image0_color'] = Vec4(0, 1, 0, 1) self.castButton['text'] = '' self.av.stopLookAround() self.__hideLine() self.__hideBob() self.howToDialog.hide() castCost = FishGlobals.getCastCost(self.av.getFishingRod()) if self.av.getMoney() < castCost: self.__hideCastGui() self.__showBroke() self.av.loop('pole-neutral') return if self.av.isFishTankFull(): self.__hideCastGui() self.__showFishTankFull() self.av.loop('pole-neutral') return self.arrow.show() self.arrow.setColorScale(1, 1, 0, 0.7) self.startAngleNP = self.angleNP.getH() self.getMouse() self.initMouseX = self.mouseX self.initMouseY = self.mouseY self.__hideBob() if config.GetBool('fishing-independent-axes', 0): taskMgr.add(self.localAdjustingCastTaskIndAxes, self.taskName('adjustCastTask')) else: taskMgr.add(self.localAdjustingCastTask, self.taskName('adjustCastTask')) if base.wantBingo: bingoMgr = self.pond.getPondBingoManager() if bingoMgr: bingoMgr.castingStarted() def exitLocalAdjusting(self): taskMgr.remove(self.taskName('adjustCastTask')) self.castButton['image0_color'] = Vec4(1, 0, 0, 1) self.castButton['text'] = TTLocalizer.FishingCast self.arrow.hide() def enterLocalCasting(self): if self.power == 0.0 and len(self.av.fishCollection) == 0: self.__showHowTo(TTLocalizer.FishingHowToFailed) if self.castTrack: self.castTrack.pause() self.av.loop('pole-neutral') self.track = None return castCost = FishGlobals.getCastCost(self.av.getFishingRod()) self.jar['text'] = str(max(self.av.getMoney() - castCost, 0)) if not self.castTrack: self.createCastTrack() self.castTrack.pause() startT = 0.7 + (1 - self.power) * 0.3 self.castTrack.start(startT) self.track = Sequence(Wait(1.2 - startT), Func(self.startMoveBobTask), Func(self.__showLineCasting)) self.track.start() heading = self.angleNP.getH() self.d_doCast(self.power, heading) self.timer.countdown(FishGlobals.CastTimeout) return def exitLocalCasting(self): taskMgr.remove(self.taskName('moveBobTask')) if self.track: self.track.pause() self.track = None if self.castTrack: self.castTrack.pause() self.__hideLine() self.__hideBob() return def enterDistCasting(self, power, h): self.av.stopLookAround() self.__placeAvatar() self.__hideLine() self.__hideBob() self.angleNP.setH(h) self.power = power self.track = Parallel(Sequence(ActorInterval(self.av, 'cast'), Func(self.pole.pose, 'cast', 0), Func(self.av.loop, 'fish-neutral')), Sequence(Wait(1.0), Func(self.startMoveBobTask), Func(self.__showLineCasting))) self.track.start() def exitDistCasting(self): self.track.finish() self.track = None taskMgr.remove(self.taskName('moveBobTask')) self.__hideLine() self.__hideBob() return def enterFishing(self): if self.localToonFishing: self.track = Sequence(ActorInterval(self.av, 'cast'), Func(self.pole.pose, 'cast', 0), Func(self.av.loop, 'fish-neutral')) self.track.start(self.castTrack.getT()) else: self.track = None self.av.loop('fish-neutral') self.__showBobFloat() self.__showLineWaiting() if self.localToonFishing: self.pond.startCheckingTargets(self, self.bob.getPos(render)) return def exitFishing(self): if self.localToonFishing: self.pond.stopCheckingTargets() if self.track: self.track.finish() self.track = None return def enterWaitForAI(self): self.castButton['state'] = DGG.DISABLED def exitWaitForAI(self): self.castButton['state'] = DGG.NORMAL def enterReward(self, code, itemDesc1, itemDesc2, itemDesc3): self.__placeAvatar() self.bob.reparentTo(self.angleNP) self.bob.setZ(self.waterLevel) self.__showLineReeling() self.castTrack.pause() if self.localToonFishing: self.__showCastGui() if code == FishGlobals.QuestItem: self.__showQuestItem(itemDesc1) elif code in (FishGlobals.FishItem, FishGlobals.FishItemNewEntry, FishGlobals.FishItemNewRecord): genus, species, weight = itemDesc1, itemDesc2, itemDesc3 fish = FishBase.FishBase(genus, species, weight) self.__showFishItem(code, fish) if base.wantBingo: self.pond.handleBingoCatch((genus, species)) elif code == FishGlobals.BootItem: self.__showBootItem() if base.wantBingo: self.pond.handleBingoCatch(FishGlobals.BingoBoot) elif code == FishGlobals.JellybeanItem: amount = itemDesc1 self.__showJellybeanItem(amount) elif code == FishGlobals.OverTankLimit: self.__hideCastGui() else: self.__showFailureReason(code) self.track = Sequence(Parallel(ActorInterval(self.av, 'reel'), ActorInterval(self.pole, 'cast', startFrame=63, endFrame=127)), ActorInterval(self.av, 'reel-neutral'), Func(self.__hideLine), Func(self.__hideBob), ActorInterval(self.av, 'fish-again'), Func(self.av.loop, 'pole-neutral')) self.track.start() def cleanupFishPanel(self): if self.fishPanel: self.fishPanel.hide() self.fishPanel.destroy() self.fishPanel = None return def hideBootPanel(self): if self.madeGui and self.itemBoot: self.__itemGuiClose() def exitReward(self): if self.localToonFishing: self.itemGui.detachNode() self.cleanupFishPanel() self.track.finish() self.track = None return def enterLeaving(self): if self.localToonFishing: self.__hideCastGui() if base.wantBingo: self.pond.cleanupBingoMgr() self.av.stopLookAround() self.av.startLookAround() self.__placeAvatar() self.__hideLine() self.__hideBob() self.track = Sequence(Parallel(ActorInterval(self.av, 'fish-end'), Func(self.pole.pose, 'cast', 0), LerpScaleInterval(self.pole, duration=0.5, scale=0.01, startScale=1.0)), Func(self.__dropPole), Func(self.av.loop, 'neutral')) if self.localToonFishing: self.track.append(Func(self.fsm.requestFinalState)) self.track.start() def exitLeaving(self): self.track.pause() self.track = None return def enterSellFish(self): self.castButton['state'] = DGG.DISABLED self.__showSellFishDialog() self.__hideHowTo() def exitSellFish(self): self.castButton['state'] = DGG.NORMAL self.__hideSellFishDialog() self.__hideSellFishConfirmDialog() def sellFishComplete(self, trophyResult, numFishCaught): for button in self.sellFishDialog.buttonList: button['state'] = DGG.NORMAL if self.localToonFishing: if trophyResult: self.__hideSellFishDialog() self.__showSellFishConfirmDialog(numFishCaught) else: self.fsm.request('waiting', [False]) def __allowSellFish(self): if base.wantBingo: if self.pond.hasPondBingoManager(): hoodId = base.cr.playGame.getPlaceId() if hoodId == ToontownGlobals.MyEstate: return True return False