789 lines
33 KiB
Python
789 lines
33 KiB
Python
|
from PurchaseBase import *
|
||
|
from direct.task.Task import Task
|
||
|
from toontown.toon import ToonHead
|
||
|
from toontown.toonbase import ToontownTimer
|
||
|
from direct.gui import DirectGuiGlobals as DGG
|
||
|
from direct.directnotify import DirectNotifyGlobal
|
||
|
from direct.showbase.PythonUtil import Functor
|
||
|
from toontown.minigame import TravelGameGlobals
|
||
|
from toontown.distributed import DelayDelete
|
||
|
from toontown.toonbase import ToontownGlobals
|
||
|
import MinigameGlobals
|
||
|
COUNT_UP_RATE = 0.15
|
||
|
COUNT_UP_DURATION = 0.5
|
||
|
DELAY_BEFORE_COUNT_UP = 1.0
|
||
|
DELAY_AFTER_COUNT_UP = 1.0
|
||
|
COUNT_DOWN_RATE = 0.075
|
||
|
COUNT_DOWN_DURATION = 0.5
|
||
|
DELAY_AFTER_COUNT_DOWN = 0.0
|
||
|
DELAY_AFTER_CELEBRATE = 2.6
|
||
|
COUNT_SFX_MIN_DELAY = 0.034
|
||
|
COUNT_SFX_START_T = 0.079
|
||
|
OVERMAX_SFX_MIN_DELAY = 0.067
|
||
|
OVERMAX_SFX_START_T = 0.021
|
||
|
|
||
|
class Purchase(PurchaseBase):
|
||
|
notify = DirectNotifyGlobal.directNotify.newCategory('Purchase')
|
||
|
|
||
|
def __init__(self, toon, pointsArray, playerMoney, ids, states, remain, doneEvent, metagameRound = -1, votesArray = None):
|
||
|
PurchaseBase.__init__(self, toon, doneEvent)
|
||
|
self.ids = ids
|
||
|
self.pointsArray = pointsArray
|
||
|
self.playerMoney = playerMoney
|
||
|
self.states = states
|
||
|
self.remain = remain
|
||
|
self.tutorialMode = 0
|
||
|
self.metagameRound = metagameRound
|
||
|
self.votesArray = votesArray
|
||
|
self.voteMultiplier = 1
|
||
|
self.fsm.addState(State.State('reward', self.enterReward, self.exitReward, ['purchase']))
|
||
|
doneState = self.fsm.getStateNamed('done')
|
||
|
doneState.addTransition('reward')
|
||
|
self.unexpectedEventNames = []
|
||
|
self.unexpectedExits = []
|
||
|
self.setupUnexpectedExitHooks()
|
||
|
|
||
|
def load(self):
|
||
|
purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui')
|
||
|
PurchaseBase.load(self, purchaseModels)
|
||
|
interiorPhase = 3.5
|
||
|
self.bg = loader.loadModel('phase_%s/models/modules/toon_interior' % interiorPhase)
|
||
|
self.bg.setPos(0.0, 5.0, -1.0)
|
||
|
self.wt = self.bg.find('**/random_tc1_TI_wallpaper')
|
||
|
wallTex = loader.loadTexture('phase_%s/maps/wall_paper_a5.jpg' % interiorPhase)
|
||
|
self.wt.setTexture(wallTex, 100)
|
||
|
self.wt.setColorScale(0.8, 0.67, 0.549, 1.0)
|
||
|
self.bt = self.bg.find('**/random_tc1_TI_wallpaper_border')
|
||
|
wallTex = loader.loadTexture('phase_%s/maps/wall_paper_a5.jpg' % interiorPhase)
|
||
|
self.bt.setTexture(wallTex, 100)
|
||
|
self.bt.setColorScale(0.8, 0.67, 0.549, 1.0)
|
||
|
self.wb = self.bg.find('**/random_tc1_TI_wainscotting')
|
||
|
wainTex = loader.loadTexture('phase_%s/maps/wall_paper_b4.jpg' % interiorPhase)
|
||
|
self.wb.setTexture(wainTex, 100)
|
||
|
self.wb.setColorScale(0.473, 0.675, 0.488, 1.0)
|
||
|
self.playAgain = DirectButton(parent=self.frame, relief=None, scale=1.04, pos=(0.72, 0, -0.24), image=(purchaseModels.find('**/PurchScrn_BTN_UP'),
|
||
|
purchaseModels.find('**/PurchScrn_BTN_DN'),
|
||
|
purchaseModels.find('**/PurchScrn_BTN_RLVR'),
|
||
|
purchaseModels.find('**/PurchScrn_BTN_UP')), text=TTLocalizer.GagShopPlayAgain, text_fg=(0, 0.1, 0.7, 1), text_scale=0.05, text_pos=(0, 0.015, 0), image3_color=Vec4(0.6, 0.6, 0.6, 1), text3_fg=Vec4(0, 0, 0.4, 1), command=self.__handlePlayAgain)
|
||
|
self.backToPlayground = DirectButton(parent=self.frame, relief=None, scale=1.04, pos=(0.72, 0, -0.045), image=(purchaseModels.find('**/PurchScrn_BTN_UP'),
|
||
|
purchaseModels.find('**/PurchScrn_BTN_DN'),
|
||
|
purchaseModels.find('**/PurchScrn_BTN_RLVR'),
|
||
|
purchaseModels.find('**/PurchScrn_BTN_UP')), text=TTLocalizer.GagShopBackToPlayground, text_fg=(0, 0.1, 0.7, 1), text_scale=0.05, text_pos=(0, 0.015, 0), image3_color=Vec4(0.6, 0.6, 0.6, 1), text3_fg=Vec4(0, 0, 0.4, 1), command=self.__handleBackToPlayground)
|
||
|
self.timer = ToontownTimer.ToontownTimer()
|
||
|
self.timer.reparentTo(self.frame)
|
||
|
self.timer.posInTopRightCorner()
|
||
|
numAvs = 0
|
||
|
count = 0
|
||
|
localToonIndex = 0
|
||
|
for index in range(len(self.ids)):
|
||
|
avId = self.ids[index]
|
||
|
if avId == base.localAvatar.doId:
|
||
|
localToonIndex = index
|
||
|
if self.states[index] != PURCHASE_NO_CLIENT_STATE and self.states[index] != PURCHASE_DISCONNECTED_STATE:
|
||
|
numAvs = numAvs + 1
|
||
|
|
||
|
layoutList = (None,
|
||
|
(0,),
|
||
|
(0, 2),
|
||
|
(0, 1, 3),
|
||
|
(0, 1, 2, 3))
|
||
|
layout = layoutList[numAvs]
|
||
|
headFramePosList = (Vec3(0.105, 0, -0.384),
|
||
|
Vec3(0.105, 0, -0.776),
|
||
|
Vec3(0.85, 0, -0.555),
|
||
|
Vec3(-0.654, 0, -0.555))
|
||
|
AVID_INDEX = 0
|
||
|
LAYOUT_INDEX = 1
|
||
|
TOON_INDEX = 2
|
||
|
self.avInfoArray = [(base.localAvatar.doId, headFramePosList[0], localToonIndex)]
|
||
|
pos = 1
|
||
|
for index in range(len(self.ids)):
|
||
|
avId = self.ids[index]
|
||
|
if self.states[index] != PURCHASE_NO_CLIENT_STATE and self.states[index] != PURCHASE_DISCONNECTED_STATE:
|
||
|
if avId != base.localAvatar.doId:
|
||
|
if base.cr.doId2do.has_key(avId):
|
||
|
self.avInfoArray.append((avId, headFramePosList[layout[pos]], index))
|
||
|
pos = pos + 1
|
||
|
|
||
|
self.headFrames = []
|
||
|
for avInfo in self.avInfoArray:
|
||
|
av = base.cr.doId2do.get(avInfo[AVID_INDEX])
|
||
|
if av:
|
||
|
headFrame = PurchaseHeadFrame(av, purchaseModels)
|
||
|
headFrame.setAvatarState(self.states[avInfo[TOON_INDEX]])
|
||
|
headFrame.setPos(avInfo[LAYOUT_INDEX])
|
||
|
self.headFrames.append((avInfo[AVID_INDEX], headFrame))
|
||
|
|
||
|
purchaseModels.removeNode()
|
||
|
self.foreground = loader.loadModel('phase_3.5/models/modules/TT_A1')
|
||
|
self.foreground.setPos(12.5, -20, -5.5)
|
||
|
self.foreground.setHpr(180, 0, 0)
|
||
|
self.backgroundL = loader.loadModel('phase_3.5/models/modules/TT_A1')
|
||
|
self.backgroundL.setPos(-12.5, -25, -5)
|
||
|
self.backgroundL.setHpr(180, 0, 0)
|
||
|
self.backgroundR = self.backgroundL.copyTo(hidden)
|
||
|
self.backgroundR.setPos(20, -25, -5)
|
||
|
streets = loader.loadModel('phase_3.5/models/modules/street_modules')
|
||
|
sidewalk = streets.find('**/street_sidewalk_40x40')
|
||
|
self.sidewalk = sidewalk.copyTo(hidden)
|
||
|
self.sidewalk.setPos(-20, -25, -5.5)
|
||
|
self.sidewalk.setColor(0.9, 0.6, 0.4)
|
||
|
streets.removeNode()
|
||
|
doors = loader.loadModel('phase_4/models/modules/doors')
|
||
|
door = doors.find('**/door_single_square_ur_door')
|
||
|
self.door = door.copyTo(hidden)
|
||
|
self.door.setH(180)
|
||
|
self.door.setPos(0, -16.75, -5.5)
|
||
|
self.door.setScale(1.5, 1.5, 2.0)
|
||
|
self.door.setColor(1.0, 0.8, 0, 1)
|
||
|
doors.removeNode()
|
||
|
self.convertingVotesToBeansLabel = DirectLabel(text=TTLocalizer.TravelGameConvertingVotesToBeans, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(0.0, 0, -0.58), scale=0.075)
|
||
|
self.convertingVotesToBeansLabel.hide()
|
||
|
self.rewardDoubledJellybeanLabel = DirectLabel(text=TTLocalizer.PartyRewardDoubledJellybean, text_fg=(1.0, 0.125, 0.125, 1.0), text_shadow=(0, 0, 0, 1), relief=None, pos=(0.0, 0, -0.67), scale=0.08)
|
||
|
self.rewardDoubledJellybeanLabel.hide()
|
||
|
self.countSound = base.loadSfx('phase_3.5/audio/sfx/tick_counter.mp3')
|
||
|
self.overMaxSound = base.loadSfx('phase_3.5/audio/sfx/AV_collision.mp3')
|
||
|
self.celebrateSound = base.loadSfx('phase_4/audio/sfx/MG_win.mp3')
|
||
|
return
|
||
|
|
||
|
def unload(self):
|
||
|
PurchaseBase.unload(self)
|
||
|
self.cleanupUnexpectedExitHooks()
|
||
|
self.bg.removeNode()
|
||
|
del self.bg
|
||
|
self.notify.debug('destroying head frames')
|
||
|
for headFrame in self.headFrames:
|
||
|
if not headFrame[1].isEmpty():
|
||
|
headFrame[1].reparentTo(hidden)
|
||
|
headFrame[1].destroy()
|
||
|
|
||
|
del self.headFrames
|
||
|
self.playAgain.destroy()
|
||
|
del self.playAgain
|
||
|
self.backToPlayground.destroy()
|
||
|
del self.backToPlayground
|
||
|
self.timer.stop()
|
||
|
del self.timer
|
||
|
for counter in self.counters:
|
||
|
counter.destroy()
|
||
|
del counter
|
||
|
|
||
|
del self.counters
|
||
|
for total in self.totalCounters:
|
||
|
total.destroy()
|
||
|
del total
|
||
|
|
||
|
del self.totalCounters
|
||
|
loader.unloadModel('phase_3.5/models/modules/TT_A1')
|
||
|
loader.unloadModel('phase_3.5/models/modules/street_modules')
|
||
|
loader.unloadModel('phase_4/models/modules/doors')
|
||
|
taskMgr.remove('countUpTask')
|
||
|
taskMgr.remove('countVotesUpTask')
|
||
|
taskMgr.remove('countDownTask')
|
||
|
taskMgr.remove('countVotesDownTask')
|
||
|
taskMgr.remove('celebrate')
|
||
|
taskMgr.remove('purchase-trans')
|
||
|
taskMgr.remove('delayAdd')
|
||
|
taskMgr.remove('delaySubtract')
|
||
|
self.foreground.removeNode()
|
||
|
del self.foreground
|
||
|
self.backgroundL.removeNode()
|
||
|
del self.backgroundL
|
||
|
self.backgroundR.removeNode()
|
||
|
del self.backgroundR
|
||
|
self.sidewalk.removeNode()
|
||
|
del self.sidewalk
|
||
|
self.door.removeNode()
|
||
|
del self.door
|
||
|
self.collisionFloor.removeNode()
|
||
|
del self.collisionFloor
|
||
|
del self.countSound
|
||
|
del self.celebrateSound
|
||
|
self.convertingVotesToBeansLabel.removeNode()
|
||
|
self.rewardDoubledJellybeanLabel.removeNode()
|
||
|
del self.convertingVotesToBeansLabel
|
||
|
del self.rewardDoubledJellybeanLabel
|
||
|
|
||
|
def showStatusText(self, text):
|
||
|
self.statusLabel['text'] = text
|
||
|
taskMgr.remove('resetStatusText')
|
||
|
taskMgr.doMethodLater(2.0, self.resetStatusText, 'resetStatusText')
|
||
|
|
||
|
def resetStatusText(self, task):
|
||
|
self.statusLabel['text'] = ''
|
||
|
return Task.done
|
||
|
|
||
|
def __handlePlayAgain(self):
|
||
|
for headFrame in self.headFrames:
|
||
|
headFrame[1].wrtReparentTo(aspect2d)
|
||
|
|
||
|
self.toon.inventory.reparentTo(hidden)
|
||
|
self.toon.inventory.hide()
|
||
|
taskMgr.remove('resetStatusText')
|
||
|
taskMgr.remove('showBrokeMsgTask')
|
||
|
self.statusLabel['text'] = TTLocalizer.GagShopWaitingOtherPlayers
|
||
|
messenger.send('purchasePlayAgain')
|
||
|
|
||
|
def handleDone(self, playAgain):
|
||
|
base.localAvatar.b_setParent(ToontownGlobals.SPHidden)
|
||
|
if playAgain:
|
||
|
self.doneStatus = {'loader': 'minigame',
|
||
|
'where': 'minigame'}
|
||
|
else:
|
||
|
self.doneStatus = {'loader': 'safeZoneLoader',
|
||
|
'where': 'playground'}
|
||
|
messenger.send(self.doneEvent)
|
||
|
|
||
|
def __handleBackToPlayground(self):
|
||
|
self.toon.inventory.reparentTo(hidden)
|
||
|
self.toon.inventory.hide()
|
||
|
messenger.send('purchaseBackToToontown')
|
||
|
|
||
|
def __timerExpired(self):
|
||
|
messenger.send('purchaseTimeout')
|
||
|
|
||
|
def findHeadFrame(self, id):
|
||
|
for headFrame in self.headFrames:
|
||
|
if headFrame[0] == id:
|
||
|
return headFrame[1]
|
||
|
|
||
|
return None
|
||
|
|
||
|
def __handleStateChange(self, playerStates):
|
||
|
self.states = playerStates
|
||
|
for avInfo in self.avInfoArray:
|
||
|
index = avInfo[2]
|
||
|
headFrame = self.findHeadFrame(avInfo[0])
|
||
|
state = self.states[index]
|
||
|
headFrame.setAvatarState(state)
|
||
|
|
||
|
def enter(self):
|
||
|
base.playMusic(self.music, looping=1, volume=0.8)
|
||
|
self.fsm.request('reward')
|
||
|
|
||
|
def enterReward(self):
|
||
|
numToons = 0
|
||
|
toonLayouts = ((2,),
|
||
|
(1, 3),
|
||
|
(0, 2, 4),
|
||
|
(0, 1, 3, 4))
|
||
|
toonPositions = (5.0,
|
||
|
1.75,
|
||
|
-0.25,
|
||
|
-1.75,
|
||
|
-5.0)
|
||
|
self.toons = []
|
||
|
self.toonsKeep = []
|
||
|
self.counters = []
|
||
|
self.totalCounters = []
|
||
|
camera.reparentTo(render)
|
||
|
base.camLens.setFov(ToontownGlobals.DefaultCameraFov)
|
||
|
camera.setPos(0, 16.0, 2.0)
|
||
|
camera.lookAt(0, 0, 0.75)
|
||
|
base.transitions.irisIn(0.4)
|
||
|
self.title.reparentTo(aspect2d)
|
||
|
self.foreground.reparentTo(render)
|
||
|
self.backgroundL.reparentTo(render)
|
||
|
self.backgroundR.reparentTo(render)
|
||
|
self.sidewalk.reparentTo(render)
|
||
|
self.door.reparentTo(render)
|
||
|
size = 20
|
||
|
z = -2.5
|
||
|
floor = CollisionPolygon(Point3(-size, -size, z), Point3(size, -size, z), Point3(size, size, z), Point3(-size, size, z))
|
||
|
floor.setTangible(1)
|
||
|
floorNode = CollisionNode('collision_floor')
|
||
|
floorNode.addSolid(floor)
|
||
|
self.collisionFloor = render.attachNewNode(floorNode)
|
||
|
NametagGlobals.setOnscreenChatForced(1)
|
||
|
for index in range(len(self.ids)):
|
||
|
avId = self.ids[index]
|
||
|
if self.states[index] != PURCHASE_NO_CLIENT_STATE and self.states[index] != PURCHASE_DISCONNECTED_STATE and avId in base.cr.doId2do:
|
||
|
numToons += 1
|
||
|
toon = base.cr.doId2do[avId]
|
||
|
toon.stopSmooth()
|
||
|
self.toons.append(toon)
|
||
|
self.toonsKeep.append(DelayDelete.DelayDelete(toon, 'Purchase.enterReward'))
|
||
|
counter = DirectLabel(parent=hidden, relief=None, pos=(0.0, 0.0, 0.0), text=str(0), text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -0.1, 0), text_font=ToontownGlobals.getSignFont())
|
||
|
counter['image'] = DGG.getDefaultDialogGeom()
|
||
|
counter['image_scale'] = (0.33, 1, 0.33)
|
||
|
counter.setScale(0.5)
|
||
|
counter.count = 0
|
||
|
counter.max = self.pointsArray[index]
|
||
|
self.counters.append(counter)
|
||
|
money = self.playerMoney[index]
|
||
|
totalCounter = DirectLabel(parent=hidden, relief=None, pos=(0.0, 0.0, 0.0), text=str(money), text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -0.1, 0), text_font=ToontownGlobals.getSignFont(), image=self.jarImage)
|
||
|
totalCounter.setScale(0.5)
|
||
|
totalCounter.count = money
|
||
|
totalCounter.max = toon.getMaxMoney()
|
||
|
self.totalCounters.append(totalCounter)
|
||
|
|
||
|
self.accept('clientCleanup', self._handleClientCleanup)
|
||
|
pos = 0
|
||
|
toonLayout = toonLayouts[numToons - 1]
|
||
|
for toon in self.toons:
|
||
|
thisPos = toonPositions[toonLayout[pos]]
|
||
|
toon.setPos(Vec3(thisPos, 1.0, -2.5))
|
||
|
toon.setHpr(Vec3(0, 0, 0))
|
||
|
toon.setAnimState('neutral', 1)
|
||
|
toon.setShadowHeight(0)
|
||
|
if not toon.isDisabled():
|
||
|
toon.reparentTo(render)
|
||
|
self.counters[pos].setPos(thisPos * -0.17, 0, toon.getHeight() / 10 + 0.25)
|
||
|
self.counters[pos].reparentTo(aspect2d)
|
||
|
self.totalCounters[pos].setPos(thisPos * -0.17, 0, -0.825)
|
||
|
self.totalCounters[pos].reparentTo(aspect2d)
|
||
|
pos += 1
|
||
|
|
||
|
self.maxPoints = max(self.pointsArray)
|
||
|
if self.votesArray:
|
||
|
self.maxVotes = max(self.votesArray)
|
||
|
numToons = len(self.toons)
|
||
|
self.voteMultiplier = TravelGameGlobals.PercentOfVotesConverted[numToons] / 100.0
|
||
|
self.maxBeansFromVotes = int(self.voteMultiplier * self.maxVotes)
|
||
|
else:
|
||
|
self.maxVotes = 0
|
||
|
self.maxBeansFromVotes = 0
|
||
|
|
||
|
def reqCountUp(state):
|
||
|
self.countUp()
|
||
|
return Task.done
|
||
|
|
||
|
countUpDelay = DELAY_BEFORE_COUNT_UP
|
||
|
taskMgr.doMethodLater(countUpDelay, reqCountUp, 'countUpTask')
|
||
|
|
||
|
def reqCountDown(state):
|
||
|
self.countDown()
|
||
|
return Task.done
|
||
|
|
||
|
countDownDelay = countUpDelay + COUNT_UP_DURATION + DELAY_AFTER_COUNT_UP
|
||
|
taskMgr.doMethodLater(countDownDelay, reqCountDown, 'countDownTask')
|
||
|
|
||
|
def celebrate(task):
|
||
|
for counter in task.counters:
|
||
|
counter.hide()
|
||
|
|
||
|
winningPoints = max(task.pointsArray)
|
||
|
for i in range(len(task.ids)):
|
||
|
if task.pointsArray[i] == winningPoints:
|
||
|
avId = task.ids[i]
|
||
|
if base.cr.doId2do.has_key(avId):
|
||
|
toon = base.cr.doId2do[avId]
|
||
|
toon.setAnimState('jump', 1.0)
|
||
|
|
||
|
base.playSfx(task.celebrateSound)
|
||
|
return Task.done
|
||
|
|
||
|
celebrateDelay = countDownDelay + COUNT_DOWN_DURATION + DELAY_AFTER_COUNT_DOWN
|
||
|
celebrateTask = taskMgr.doMethodLater(celebrateDelay, celebrate, 'celebrate')
|
||
|
celebrateTask.counters = self.counters
|
||
|
celebrateTask.pointsArray = self.pointsArray
|
||
|
celebrateTask.ids = self.ids
|
||
|
celebrateTask.celebrateSound = self.celebrateSound
|
||
|
|
||
|
def reqCountVotesUp(state):
|
||
|
self.countVotesUp()
|
||
|
return Task.done
|
||
|
|
||
|
def reqCountVotesDown(state):
|
||
|
self.countVotesDown()
|
||
|
return Task.done
|
||
|
|
||
|
if self.metagameRound == TravelGameGlobals.FinalMetagameRoundIndex:
|
||
|
countVotesUpDelay = celebrateDelay + DELAY_AFTER_CELEBRATE
|
||
|
taskMgr.doMethodLater(countVotesUpDelay, reqCountVotesUp, 'countVotesUpTask')
|
||
|
countVotesUpTime = self.maxVotes * COUNT_UP_RATE + DELAY_AFTER_COUNT_UP
|
||
|
countVotesDownDelay = countVotesUpDelay + countVotesUpTime
|
||
|
taskMgr.doMethodLater(countVotesDownDelay, reqCountVotesDown, 'countVotesDownTask')
|
||
|
celebrateDelay += countVotesUpTime + self.maxVotes * COUNT_DOWN_RATE + DELAY_AFTER_COUNT_DOWN
|
||
|
|
||
|
def reqPurchase(state):
|
||
|
self.fsm.request('purchase')
|
||
|
return Task.done
|
||
|
|
||
|
purchaseDelay = celebrateDelay + DELAY_AFTER_CELEBRATE
|
||
|
taskMgr.doMethodLater(purchaseDelay, reqPurchase, 'purchase-trans')
|
||
|
if base.skipMinigameReward:
|
||
|
self.fsm.request('purchase')
|
||
|
return
|
||
|
|
||
|
def _changeCounterUp(self, task, counter, newCount, toonId):
|
||
|
counter.count = newCount
|
||
|
counter['text'] = str(counter.count)
|
||
|
if toonId == base.localAvatar.doId:
|
||
|
now = globalClock.getRealTime()
|
||
|
if task.lastSfxT + COUNT_SFX_MIN_DELAY < now:
|
||
|
base.playSfx(task.countSound, time=COUNT_SFX_START_T)
|
||
|
task.lastSfxT = now
|
||
|
|
||
|
def _countUpTask(self, task):
|
||
|
now = globalClock.getRealTime()
|
||
|
startT = task.getStartTime()
|
||
|
if now >= startT + task.duration:
|
||
|
for counter, toonId in zip(self.counters, self.ids):
|
||
|
if counter.count != counter.max:
|
||
|
self._changeCounterUp(task, counter, counter.max, toonId)
|
||
|
|
||
|
return Task.done
|
||
|
t = (now - startT) / task.duration
|
||
|
for counter, toonId in zip(self.counters, self.ids):
|
||
|
curCount = int(triglerp(0, counter.max, t))
|
||
|
if curCount != counter.count:
|
||
|
self._changeCounterUp(task, counter, curCount, toonId)
|
||
|
|
||
|
return Task.cont
|
||
|
|
||
|
def countUp(self):
|
||
|
totalDelay = 0
|
||
|
if base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_TROLLEY_HOLIDAY) or base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_TROLLEY_HOLIDAY_MONTH):
|
||
|
self.rewardDoubledJellybeanLabel.show()
|
||
|
countUpTask = taskMgr.add(self._countUpTask, 'countUp')
|
||
|
countUpTask.duration = COUNT_UP_DURATION
|
||
|
countUpTask.countSound = self.countSound
|
||
|
countUpTask.lastSfxT = 0
|
||
|
|
||
|
def _changeCounterDown(self, task, counter, newCount, total, toonId):
|
||
|
counter.count = newCount
|
||
|
counter['text'] = str(counter.count)
|
||
|
total.count = total.startAmount + (counter.max - newCount)
|
||
|
if total.count > total.max:
|
||
|
total.count = total.max
|
||
|
total['text'] = str(total.count)
|
||
|
if total.count == total.max:
|
||
|
total['text_fg'] = (1, 0, 0, 1)
|
||
|
if toonId == base.localAvatar.doId:
|
||
|
now = globalClock.getRealTime()
|
||
|
if total.count < total.max:
|
||
|
minDelay = COUNT_SFX_MIN_DELAY
|
||
|
snd = task.countSound
|
||
|
startT = COUNT_SFX_START_T
|
||
|
else:
|
||
|
minDelay = OVERMAX_SFX_MIN_DELAY
|
||
|
snd = task.overMaxSound
|
||
|
startT = OVERMAX_SFX_START_T
|
||
|
if task.lastSfxT + minDelay < now:
|
||
|
task.lastSfxT = now
|
||
|
base.playSfx(snd, time=startT)
|
||
|
|
||
|
def _countDownTask(self, task):
|
||
|
now = globalClock.getRealTime()
|
||
|
startT = task.getStartTime()
|
||
|
if now >= startT + task.duration:
|
||
|
for counter, total, toonId in zip(self.counters, self.totalCounters, self.ids):
|
||
|
if counter.count != 0:
|
||
|
self._changeCounterDown(task, counter, 0, total, toonId)
|
||
|
|
||
|
return Task.done
|
||
|
t = (now - startT) / task.duration
|
||
|
for counter, total, toonId in zip(self.counters, self.totalCounters, self.ids):
|
||
|
curCount = int(triglerp(counter.max, 0, t))
|
||
|
if curCount != counter.count:
|
||
|
self._changeCounterDown(task, counter, curCount, total, toonId)
|
||
|
|
||
|
return Task.cont
|
||
|
|
||
|
def countDown(self):
|
||
|
totalDelay = 0
|
||
|
for total in self.totalCounters:
|
||
|
total.startAmount = total.count
|
||
|
|
||
|
countDownTask = taskMgr.add(self._countDownTask, 'countDown')
|
||
|
countDownTask.duration = COUNT_DOWN_DURATION
|
||
|
countDownTask.countSound = self.countSound
|
||
|
countDownTask.overMaxSound = self.overMaxSound
|
||
|
countDownTask.lastSfxT = 0
|
||
|
|
||
|
def countVotesUp(self):
|
||
|
totalDelay = 0
|
||
|
self.convertingVotesToBeansLabel.show()
|
||
|
if base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_TROLLEY_HOLIDAY) or base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_TROLLEY_HOLIDAY_MONTH):
|
||
|
self.rewardDoubledJellybeanLabel.show()
|
||
|
counterIndex = 0
|
||
|
for index in range(len(self.ids)):
|
||
|
avId = self.ids[index]
|
||
|
if self.states[index] != PURCHASE_NO_CLIENT_STATE and self.states[index] != PURCHASE_DISCONNECTED_STATE and avId in base.cr.doId2do:
|
||
|
self.counters[counterIndex].count = 0
|
||
|
self.counters[counterIndex].max = self.votesArray[index]
|
||
|
self.counters[counterIndex].show()
|
||
|
counterIndex += 1
|
||
|
|
||
|
def delayAdd(state):
|
||
|
state.counter.count += 1
|
||
|
state.counter['text'] = str(state.counter.count)
|
||
|
if state.toonId == base.localAvatar.doId:
|
||
|
base.playSfx(state.countSound)
|
||
|
return Task.done
|
||
|
|
||
|
for count in range(0, self.maxVotes):
|
||
|
for counter in self.counters:
|
||
|
index = self.counters.index(counter)
|
||
|
if count < counter.max:
|
||
|
addTask = taskMgr.doMethodLater(totalDelay, delayAdd, 'delayAdd')
|
||
|
addTask.counter = counter
|
||
|
addTask.toonId = self.ids[index]
|
||
|
addTask.countSound = self.countSound
|
||
|
|
||
|
totalDelay += COUNT_UP_RATE
|
||
|
|
||
|
def countVotesDown(self):
|
||
|
totalDelay = 0
|
||
|
|
||
|
def delaySubtract(state):
|
||
|
state.counter.count -= 1
|
||
|
state.counter['text'] = str(state.counter.count)
|
||
|
state.total.count += 1 * self.voteMultiplier
|
||
|
if state.total.count <= state.total.max:
|
||
|
state.total['text'] = str(int(state.total.count))
|
||
|
if state.total.count == state.total.max + 1:
|
||
|
state.total['text_fg'] = (1, 0, 0, 1)
|
||
|
if state.toonId == base.localAvatar.doId:
|
||
|
if state.total.count <= state.total.max:
|
||
|
base.playSfx(state.countSound)
|
||
|
else:
|
||
|
base.playSfx(state.overMaxSound)
|
||
|
return Task.done
|
||
|
|
||
|
for count in range(0, self.maxVotes):
|
||
|
for counter in self.counters:
|
||
|
if count < counter.max:
|
||
|
index = self.counters.index(counter)
|
||
|
subtractTask = taskMgr.doMethodLater(totalDelay, delaySubtract, 'delaySubtract')
|
||
|
subtractTask.counter = counter
|
||
|
subtractTask.total = self.totalCounters[index]
|
||
|
subtractTask.toonId = self.ids[index]
|
||
|
subtractTask.countSound = self.countSound
|
||
|
subtractTask.overMaxSound = self.overMaxSound
|
||
|
|
||
|
totalDelay += COUNT_DOWN_RATE
|
||
|
|
||
|
def exitReward(self):
|
||
|
self.ignore('clientCleanup')
|
||
|
taskMgr.remove('countUpTask')
|
||
|
taskMgr.remove('countVotesUpTask')
|
||
|
taskMgr.remove('countDownTask')
|
||
|
taskMgr.remove('countVotesDownTask')
|
||
|
taskMgr.remove('celebrate')
|
||
|
taskMgr.remove('purchase-trans')
|
||
|
taskMgr.remove('delayAdd')
|
||
|
taskMgr.remove('delaySubtract')
|
||
|
for toon in self.toons:
|
||
|
toon.detachNode()
|
||
|
|
||
|
del self.toons
|
||
|
if hasattr(self, 'toonsKeep'):
|
||
|
for delayDelete in self.toonsKeep:
|
||
|
delayDelete.destroy()
|
||
|
|
||
|
del self.toonsKeep
|
||
|
for counter in self.counters:
|
||
|
counter.reparentTo(hidden)
|
||
|
|
||
|
for total in self.totalCounters:
|
||
|
total.reparentTo(hidden)
|
||
|
|
||
|
self.foreground.reparentTo(hidden)
|
||
|
self.backgroundL.reparentTo(hidden)
|
||
|
self.backgroundR.reparentTo(hidden)
|
||
|
self.sidewalk.reparentTo(hidden)
|
||
|
self.door.reparentTo(hidden)
|
||
|
self.title.reparentTo(self.frame)
|
||
|
self.convertingVotesToBeansLabel.hide()
|
||
|
self.rewardDoubledJellybeanLabel.hide()
|
||
|
NametagGlobals.setOnscreenChatForced(0)
|
||
|
|
||
|
def _handleClientCleanup(self):
|
||
|
if hasattr(self, 'toonsKeep'):
|
||
|
for delayDelete in self.toonsKeep:
|
||
|
delayDelete.destroy()
|
||
|
|
||
|
del self.toonsKeep
|
||
|
self.ignore('clientCleanup')
|
||
|
|
||
|
def enterPurchase(self):
|
||
|
PurchaseBase.enterPurchase(self)
|
||
|
self.convertingVotesToBeansLabel.hide()
|
||
|
self.rewardDoubledJellybeanLabel.hide()
|
||
|
self.bg.reparentTo(render)
|
||
|
base.setBackgroundColor(0.05, 0.14, 0.4)
|
||
|
self.accept('purchaseStateChange', self.__handleStateChange)
|
||
|
self.playAgain.reparentTo(self.toon.inventory.purchaseFrame)
|
||
|
self.backToPlayground.reparentTo(self.toon.inventory.purchaseFrame)
|
||
|
self.pointDisplay.reparentTo(self.toon.inventory.purchaseFrame)
|
||
|
self.statusLabel.reparentTo(self.toon.inventory.purchaseFrame)
|
||
|
for headFrame in self.headFrames:
|
||
|
headFrame[1].show()
|
||
|
headFrame[1].reparentTo(self.toon.inventory.purchaseFrame)
|
||
|
|
||
|
if base.cr.periodTimerExpired:
|
||
|
base.cr.loginFSM.request('periodTimeout')
|
||
|
return
|
||
|
if not self.tutorialMode:
|
||
|
if not config.GetBool('disable-purchase-timer', 0):
|
||
|
self.timer.countdown(self.remain, self.__timerExpired)
|
||
|
if config.GetBool('metagame-disable-playAgain', 0):
|
||
|
if self.metagameRound > -1:
|
||
|
self.disablePlayAgain()
|
||
|
else:
|
||
|
self.timer.hide()
|
||
|
self.disablePlayAgain()
|
||
|
self.accept('disableGagPanel', Functor(self.toon.inventory.setActivateMode, 'gagTutDisabled', gagTutMode=1))
|
||
|
self.accept('disableBackToPlayground', self.disableBackToPlayground)
|
||
|
self.accept('enableGagPanel', self.handleEnableGagPanel)
|
||
|
self.accept('enableBackToPlayground', self.enableBackToPlayground)
|
||
|
for avId, headFrame in self.headFrames:
|
||
|
if avId != self.newbieId:
|
||
|
headFrame.hide()
|
||
|
|
||
|
messenger.send('gagScreenIsUp')
|
||
|
if base.autoPlayAgain or self.doMetagamePlayAgain():
|
||
|
base.transitions.fadeOut(0)
|
||
|
self.__handlePlayAgain()
|
||
|
|
||
|
def exitPurchase(self):
|
||
|
PurchaseBase.exitPurchase(self)
|
||
|
self.ignore('disableGagPanel')
|
||
|
self.ignore('disableBackToPlayground')
|
||
|
self.ignore('enableGagPanel')
|
||
|
self.ignore('enableBackToPlayground')
|
||
|
self.bg.reparentTo(hidden)
|
||
|
self.playAgain.reparentTo(self.frame)
|
||
|
self.backToPlayground.reparentTo(self.frame)
|
||
|
self.pointDisplay.reparentTo(self.frame)
|
||
|
self.statusLabel.reparentTo(self.frame)
|
||
|
self.ignore('purchaseStateChange')
|
||
|
base.setBackgroundColor(ToontownGlobals.DefaultBackgroundColor)
|
||
|
if base.autoPlayAgain or self.doMetagamePlayAgain():
|
||
|
base.transitions.fadeIn()
|
||
|
|
||
|
def disableBackToPlayground(self):
|
||
|
self.backToPlayground['state'] = DGG.DISABLED
|
||
|
|
||
|
def enableBackToPlayground(self):
|
||
|
self.backToPlayground['state'] = DGG.NORMAL
|
||
|
|
||
|
def disablePlayAgain(self):
|
||
|
self.playAgain['state'] = DGG.DISABLED
|
||
|
|
||
|
def enablePlayAgain(self):
|
||
|
self.playAgain['state'] = DGG.NORMAL
|
||
|
|
||
|
def enterTutorialMode(self, newbieId):
|
||
|
self.tutorialMode = 1
|
||
|
self.newbieId = newbieId
|
||
|
|
||
|
def handleEnableGagPanel(self):
|
||
|
self.toon.inventory.setActivateMode('purchase', gagTutMode=1)
|
||
|
self.checkForBroke()
|
||
|
|
||
|
def handleGagTutorialDone(self):
|
||
|
self.enableBackToPlayground()
|
||
|
|
||
|
def doMetagamePlayAgain(self):
|
||
|
if hasattr(self, 'metagamePlayAgainResult'):
|
||
|
return self.metagamePlayAgainResult
|
||
|
numToons = 0
|
||
|
for avId in self.ids:
|
||
|
if base.cr.doId2do.has_key(avId) and avId not in self.unexpectedExits:
|
||
|
numToons += 1
|
||
|
|
||
|
self.metagamePlayAgainResult = False
|
||
|
if numToons > 1:
|
||
|
if self.metagameRound > -1 and self.metagameRound < TravelGameGlobals.FinalMetagameRoundIndex:
|
||
|
self.metagamePlayAgainResult = True
|
||
|
return self.metagamePlayAgainResult
|
||
|
|
||
|
def setupUnexpectedExitHooks(self):
|
||
|
for avId in self.ids:
|
||
|
if base.cr.doId2do.has_key(avId):
|
||
|
toon = base.cr.doId2do[avId]
|
||
|
eventName = toon.uniqueName('disable')
|
||
|
self.accept(eventName, self.__handleUnexpectedExit, extraArgs=[avId])
|
||
|
self.unexpectedEventNames.append(eventName)
|
||
|
|
||
|
def cleanupUnexpectedExitHooks(self):
|
||
|
for eventName in self.unexpectedEventNames:
|
||
|
self.ignore(eventName)
|
||
|
|
||
|
def __handleUnexpectedExit(self, avId):
|
||
|
self.unexpectedExits.append(avId)
|
||
|
|
||
|
|
||
|
class PurchaseHeadFrame(DirectFrame):
|
||
|
notify = DirectNotifyGlobal.directNotify.newCategory('Purchase')
|
||
|
|
||
|
def __init__(self, av, purchaseModels):
|
||
|
DirectFrame.__init__(self, relief=None, image=purchaseModels.find('**/Char_Pnl'))
|
||
|
self.initialiseoptions(PurchaseHeadFrame)
|
||
|
self.statusLabel = DirectLabel(parent=self, relief=None, text='', text_scale=TTLocalizer.PstatusLabel, text_wordwrap=7.5, text_fg=(0.05, 0.14, 0.4, 1), text_pos=(0.1, 0, 0))
|
||
|
self.av = av
|
||
|
self.avKeep = DelayDelete.DelayDelete(av, 'PurchaseHeadFrame.av')
|
||
|
self.accept('clientCleanup', self._handleClientCleanup)
|
||
|
self.head = self.stateNodePath[0].attachNewNode('head', 20)
|
||
|
self.head.setPosHprScale(-0.22, 10.0, -0.1, 180.0, 0.0, 0.0, 0.1, 0.1, 0.1)
|
||
|
self.headModel = ToonHead.ToonHead()
|
||
|
self.headModel.setupHead(self.av.style, forGui=1)
|
||
|
self.headModel.reparentTo(self.head)
|
||
|
self.tag2Node = NametagFloat2d()
|
||
|
self.tag2Node.setContents(Nametag.CName)
|
||
|
self.av.nametag.addNametag(self.tag2Node)
|
||
|
self.tag2 = self.attachNewNode(self.tag2Node.upcastToPandaNode())
|
||
|
self.tag2.setPosHprScale(-0.22, 10.0, 0.12, 0, 0, 0, 0.046, 0.046, 0.046)
|
||
|
self.tag1Node = NametagFloat2d()
|
||
|
self.tag1Node.setContents(Nametag.CSpeech | Nametag.CThought)
|
||
|
self.av.nametag.addNametag(self.tag1Node)
|
||
|
self.tag1 = self.attachNewNode(self.tag1Node.upcastToPandaNode())
|
||
|
self.tag1.setPosHprScale(-0.15, 0, -0.1, 0, 0, 0, 0.046, 0.046, 0.046)
|
||
|
self.hide()
|
||
|
return
|
||
|
|
||
|
def destroy(self):
|
||
|
DirectFrame.destroy(self)
|
||
|
del self.statusLabel
|
||
|
self.headModel.delete()
|
||
|
del self.headModel
|
||
|
self.head.removeNode()
|
||
|
del self.head
|
||
|
self.av.nametag.removeNametag(self.tag1Node)
|
||
|
self.av.nametag.removeNametag(self.tag2Node)
|
||
|
self.tag1.removeNode()
|
||
|
self.tag2.removeNode()
|
||
|
del self.tag1
|
||
|
del self.tag2
|
||
|
del self.tag1Node
|
||
|
del self.tag2Node
|
||
|
del self.av
|
||
|
self.removeAvKeep()
|
||
|
|
||
|
def setAvatarState(self, state):
|
||
|
if state == PURCHASE_DISCONNECTED_STATE:
|
||
|
self.statusLabel['text'] = TTLocalizer.GagShopPlayerDisconnected % self.av.getName()
|
||
|
self.statusLabel['text_pos'] = (0.015, 0.072, 0)
|
||
|
self.head.hide()
|
||
|
self.tag1.hide()
|
||
|
self.tag2.hide()
|
||
|
elif state == PURCHASE_EXIT_STATE:
|
||
|
self.statusLabel['text'] = TTLocalizer.GagShopPlayerExited % self.av.getName()
|
||
|
self.statusLabel['text_pos'] = (0.015, 0.072, 0)
|
||
|
self.head.hide()
|
||
|
self.tag1.hide()
|
||
|
self.tag2.hide()
|
||
|
elif state == PURCHASE_PLAYAGAIN_STATE:
|
||
|
self.statusLabel['text'] = TTLocalizer.GagShopPlayerPlayAgain
|
||
|
self.statusLabel['text_pos'] = (0.1, -0.12, 0)
|
||
|
elif state == PURCHASE_WAITING_STATE:
|
||
|
self.statusLabel['text'] = TTLocalizer.GagShopPlayerBuying
|
||
|
self.statusLabel['text_pos'] = (0.1, -0.12, 0)
|
||
|
elif state == PURCHASE_NO_CLIENT_STATE:
|
||
|
Purchase.notify.warning("setAvatarState('no client state'); OK for gag purchase tutorial")
|
||
|
else:
|
||
|
Purchase.notify.warning('unknown avatar state: %s' % state)
|
||
|
|
||
|
def _handleClientCleanup(self):
|
||
|
self.destroy()
|
||
|
|
||
|
def removeAvKeep(self):
|
||
|
if hasattr(self, 'avKeep'):
|
||
|
self.notify.debug('destroying avKeep %s' % self.avKeep)
|
||
|
self.avKeep.destroy()
|
||
|
del self.avKeep
|
||
|
self.ignore('clientCleanup')
|