toontown-just-works/toontown/safezone/DistributedFishingSpot.py
2024-07-07 18:08:39 -05:00

1054 lines
42 KiB
Python

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
class DistributedFishingSpot(DistributedObject.DistributedObject):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedFishingSpot')
vZeroMax = 25.0
angleMax = 30.0
def __init__(self, cr):
if hasattr(self, 'fishInit'):
return
self.fishInit = 1
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.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
for event in self.getAllAccepting():
if event.startswith('generate-'):
self.ignore(event)
DistributedObject.DistributedObject.disable(self)
return
def delete(self):
if hasattr(self, 'fishDeleted'):
return
self.fishDeleted = 1
del self.pond
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 pondDoId in self.cr.doId2do:
self.setPond(self.cr.doId2do[pondDoId])
else:
self.acceptOnce('generate-%d' % pondDoId, self.setPond)
def setPond(self, pond):
self.pond = pond
self.area = self.pond.getArea()
self.waterLevel = FishingTargetGlobals.getWaterLevel(self.area)
def __handleEnterSphere(self, collEntry):
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()
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 avId and avId not in self.cr.doId2do:
def tryAgain(av):
def reposition(task):
self.setOccupied(avId)
return task.done
taskMgr.doMethodLater(0.1, reposition, self.uniqueName('reposition'))
self.acceptOnce('generate-%d' % avId, tryAgain)
return
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)
self.av = self.cr.doId2do.get(self.avId)
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()
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.loadSfx('phase_4/audio/sfx/TT_splash1.ogg'), base.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.cleanup()
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(aspect2d)
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.fishBingoTutorialDone:
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.exitButton.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.setBin("background", 10)
self.castGui.setScale(0.67)
self.castGui.setPos(0, 1, 0)
for nodeName in ('bucket', 'jar', 'display_bucket', 'display_jar'):
self.castGui.find('**/' + nodeName).reparentTo(self.castGui)
self.exitButton = DirectButton(parent=base.a2dBottomRight, 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=(-0.218, 0, 0.11), scale=0.8, 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):
if not self.castGui:
return
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.waterLevel = FishingTargetGlobals.getWaterLevel(self.area)
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):
return base.wantBingo and self.pond.hasPondBingoManager()