from pandac.PandaModules import * from toontown.toonbase.ToonBaseGlobal import * from direct.distributed.ClockDelta import * from direct.interval.IntervalGlobal import * from .DistributedMinigame import * from direct.gui.DirectGui import * from pandac.PandaModules import * from direct.fsm import ClassicFSM, State from direct.fsm import State from direct.task.Task import Task from toontown.toonbase import ToontownTimer from . import RaceGameGlobals from toontown.toonbase import ToontownGlobals from toontown.toonbase import TTLocalizer class DistributedRaceGame(DistributedMinigame): def __init__(self, cr): DistributedMinigame.__init__(self, cr) self.gameFSM = ClassicFSM.ClassicFSM('DistributedRaceGame', [State.State('off', self.enterOff, self.exitOff, ['inputChoice']), State.State('inputChoice', self.enterInputChoice, self.exitInputChoice, ['waitServerChoices', 'moveAvatars', 'cleanup']), State.State('waitServerChoices', self.enterWaitServerChoices, self.exitWaitServerChoices, ['moveAvatars', 'cleanup']), State.State('moveAvatars', self.enterMoveAvatars, self.exitMoveAvatars, ['inputChoice', 'winMovie', 'cleanup']), State.State('winMovie', self.enterWinMovie, self.exitWinMovie, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) self.posHprArray = (((-9.03, 0.06, 0.025, -152.9), (-7.43, -2.76, 0.025, -152.68), (-6.02, -5.48, 0.025, -157.54), (-5.01, -8.32, 0.025, -160.66), (-4.05, -11.36, 0.025, -170.22), (-3.49, -14.18, 0.025, -175.76), (-3.12, -17.15, 0.025, -177.73), (-3.0, -20.32, 0.025, 178.49), (-3.09, -23.44, 0.025, 176.59), (-3.43, -26.54, 0.025, 171.44), (-4.07, -29.44, 0.025, 163.75), (-5.09, -32.27, 0.025, 158.2), (-6.11, -35.16, 0.025, 154.98), (-7.57, -37.78, 0.025, 154.98), (-9.28, -40.65, 0.025, 150.41)), ((-6.12, 1.62, 0.025, -152.9), (-4.38, -1.35, 0.025, -150.92), (-3.08, -4.3, 0.025, -157.9), (-1.85, -7.26, 0.025, -162.54), (-0.93, -10.49, 0.025, -167.71), (-0.21, -13.71, 0.025, -171.79), (0.21, -17.08, 0.025, -174.92), (0.31, -20.2, 0.025, 177.1), (0.17, -23.66, 0.025, 174.82), (-0.23, -26.91, 0.025, 170.51), (-0.99, -30.2, 0.025, 162.54), (-2.02, -33.28, 0.025, 160.48), (-3.28, -36.38, 0.025, 157.96), (-4.67, -39.17, 0.025, 154.13), (-6.31, -42.15, 0.025, 154.13)), ((-2.99, 3.09, 0.025, -154.37), (-1.38, -0.05, 0.025, -154.75), (-0.19, -3.29, 0.025, -159.22), (1.17, -6.51, 0.025, -162.74), (2.28, -9.8, 0.025, -168.73), (3.09, -13.28, 0.025, -173.49), (3.46, -16.63, 0.025, -176.81), (3.69, -20.38, 0.025, 179.14), (3.61, -24.12, 0.025, 175.78), (3.0, -27.55, 0.025, 170.87), (2.15, -30.72, 0.025, 167.41), (1.04, -34.26, 0.025, 162.11), (-0.15, -37.44, 0.025, 158.59), (-1.64, -40.52, 0.025, 153.89), (-3.42, -43.63, 0.025, 153.89)), ((0.0, 4.35, 0.025, -154.37), (1.52, 1.3, 0.025, -155.67), (3.17, -2.07, 0.025, -155.67), (4.47, -5.41, 0.025, -163.0), (5.56, -9.19, 0.025, -168.89), (6.22, -12.66, 0.025, -171.67), (6.67, -16.56, 0.025, -176.53), (6.93, -20.33, 0.025, 179.87), (6.81, -24.32, 0.025, 175.19), (6.22, -27.97, 0.025, 170.81), (5.59, -31.73, 0.025, 167.54), (4.48, -35.42, 0.025, 161.92), (3.06, -38.82, 0.025, 158.56), (1.4, -42.0, 0.025, 154.32), (-0.71, -45.17, 0.025, 153.27))) self.avatarPositions = {} self.modelCount = 8 self.cameraTopView = (-22.78, -41.65, 31.53, -51.55, -42.68, -2.96) self.timer = None self.timerStartTime = None return None def getTitle(self): return TTLocalizer.RaceGameTitle def getInstructions(self): return TTLocalizer.RaceGameInstructions def getMaxDuration(self): return 60 def load(self): self.notify.debug('load') DistributedMinigame.load(self) self.raceBoard = loader.loadModel('phase_4/models/minigames/race') self.raceBoard.setPosHpr(0, 0, 0, 0, 0, 0) self.raceBoard.setScale(0.8) self.dice = loader.loadModel('phase_4/models/minigames/dice') self.dice1 = self.dice.find('**/dice_button1') self.dice2 = self.dice.find('**/dice_button2') self.dice3 = self.dice.find('**/dice_button3') self.dice4 = self.dice.find('**/dice_button4') self.diceList = [self.dice1, self.dice2, self.dice3, self.dice4] self.music = base.loader.loadMusic('phase_4/audio/bgm/minigame_race.mid') self.posBuzzer = base.loader.loadSfx('phase_4/audio/sfx/MG_pos_buzzer.wav') self.negBuzzer = base.loader.loadSfx('phase_4/audio/sfx/MG_neg_buzzer.wav') self.winSting = base.loader.loadSfx('phase_4/audio/sfx/MG_win.mp3') self.loseSting = base.loader.loadSfx('phase_4/audio/sfx/MG_lose.mp3') self.diceButtonList = [] for i in range(1, 5): button = self.dice.find('**/dice_button' + str(i)) button_down = self.dice.find('**/dice_button' + str(i) + '_down') button_ro = self.dice.find('**/dice_button' + str(i) + '_ro') diceButton = DirectButton(image=(button, button_down, button_ro, None), relief=None, pos=(-0.9 + (i - 1) * 0.2, 0.0, -0.85), scale=0.25, command=self.handleInputChoice, extraArgs=[i]) diceButton.hide() self.diceButtonList.append(diceButton) self.waitingChoicesLabel = DirectLabel(text=TTLocalizer.RaceGameWaitingChoices, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075) self.waitingChoicesLabel.hide() self.chanceMarker = loader.loadModel('phase_4/models/minigames/question_mark') self.chanceCard = loader.loadModel('phase_4/models/minigames/chance_card') self.chanceCardText = OnscreenText('', fg=(1.0, 0, 0, 1), scale=0.14, font=ToontownGlobals.getSignFont(), wordwrap=14, pos=(0.0, 0.2), mayChange=1) self.chanceCardText.hide() self.cardSound = base.loader.loadSfx('phase_3.5/audio/sfx/GUI_stickerbook_turn.mp3') self.chanceMarkers = [] return def unload(self): self.notify.debug('unload') DistributedMinigame.unload(self) self.raceBoard.removeNode() del self.raceBoard self.dice.removeNode() del self.dice self.chanceMarker.removeNode() del self.chanceMarker self.chanceCardText.removeNode() del self.chanceCardText self.chanceCard.removeNode() del self.chanceCard self.waitingChoicesLabel.destroy() del self.waitingChoicesLabel del self.music del self.posBuzzer del self.negBuzzer del self.winSting del self.loseSting del self.cardSound for button in self.diceButtonList: button.destroy() del self.diceButtonList for marker in self.chanceMarkers: marker.removeNode() del marker del self.chanceMarkers self.removeChildGameFSM(self.gameFSM) del self.gameFSM def onstage(self): self.notify.debug('onstage') DistributedMinigame.onstage(self) base.playMusic(self.music, looping=1, volume=0.8) self.raceBoard.reparentTo(render) camera.reparentTo(render) p = self.cameraTopView camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5]) base.transitions.irisIn(0.4) base.setBackgroundColor(0.1875, 0.7929, 0) def offstage(self): self.notify.debug('offstage') DistributedMinigame.offstage(self) self.music.stop() base.setBackgroundColor(ToontownGlobals.DefaultBackgroundColor) self.raceBoard.reparentTo(hidden) self.chanceCard.reparentTo(hidden) self.chanceCardText.hide() if hasattr(self, 'chanceMarkers'): for marker in self.chanceMarkers: marker.reparentTo(hidden) def setGameReady(self): if not self.hasLocalToon: return self.notify.debug('setGameReady') if DistributedMinigame.setGameReady(self): return self.resetPositions() for i in range(self.numPlayers): avId = self.avIdList[i] if self.localAvId == avId: self.localAvLane = i avatar = self.getAvatar(avId) if avatar: avatar.reparentTo(render) avatar.setAnimState('neutral', 1) self.positionInPlace(avatar, i, 0) def setGameStart(self, timestamp): if not self.hasLocalToon: return self.notify.debug('setGameStart') DistributedMinigame.setGameStart(self, timestamp) self.gameFSM.request('inputChoice') def enterOff(self): self.notify.debug('enterOff') def exitOff(self): pass def enterInputChoice(self): self.notify.debug('enterInputChoice') for button in self.diceButtonList: button.show() self.timer = ToontownTimer.ToontownTimer() self.timer.hide() if self.timerStartTime != None: self.startTimer() return def startTimer(self): now = globalClock.getFrameTime() elapsed = now - self.timerStartTime self.timer.posInTopRightCorner() self.timer.setTime(RaceGameGlobals.InputTimeout) self.timer.countdown(RaceGameGlobals.InputTimeout - elapsed, self.handleChoiceTimeout) self.timer.show() def setTimerStartTime(self, timestamp): if not self.hasLocalToon: return self.timerStartTime = globalClockDelta.networkToLocalTime(timestamp) if self.timer != None: self.startTimer() return def exitInputChoice(self): for button in self.diceButtonList: button.hide() if self.timer != None: self.timer.destroy() self.timer = None self.timerStartTime = None self.ignore('diceButton') return def handleChoiceTimeout(self): self.sendUpdate('setAvatarChoice', [0]) self.gameFSM.request('waitServerChoices') def handleInputChoice(self, choice): self.sendUpdate('setAvatarChoice', [choice]) self.gameFSM.request('waitServerChoices') def enterWaitServerChoices(self): self.notify.debug('enterWaitServerChoices') self.waitingChoicesLabel.show() def exitWaitServerChoices(self): self.waitingChoicesLabel.hide() def localToonWon(self): localToonPosition = self.avatarPositions[self.localAvId] if localToonPosition >= RaceGameGlobals.NumberToWin: self.notify.debug('localToon won') return 1 else: return 0 def anyAvatarWon(self): for position in list(self.avatarPositions.values()): if position >= RaceGameGlobals.NumberToWin: self.notify.debug('anyAvatarWon: Somebody won') return 1 self.notify.debug('anyAvatarWon: Nobody won') return 0 def showNumbers(self, task): self.notify.debug('showing numbers...') self.diceInstanceList = [] for i in range(len(task.choiceList)): avId = self.avIdList[i] choice = task.choiceList[i] if choice == 0: self.diceInstanceList.append(None) else: diceInstance = self.diceList[choice - 1].copyTo(self.raceBoard) self.diceInstanceList.append(diceInstance) dicePosition = self.avatarPositions[avId] + 1 diceInstance.setScale(4.0) self.positionInPlace(diceInstance, i, dicePosition) diceInstance.setP(-90) diceInstance.setZ(0.05) diceInstance.setDepthOffset(1) return Task.done def showMatches(self, task): self.notify.debug('showing matches...') for i in range(len(task.choiceList)): avId = self.avIdList[i] choice = task.choiceList[i] if choice != 0: diceInstance = self.diceInstanceList[i] freq = task.choiceList.count(choice) if freq == 1: diceInstance.setColor(0.2, 1, 0.2, 1) if avId == self.localAvId: base.playSfx(self.posBuzzer) else: diceInstance.setColor(1, 0.2, 0.2, 1) if avId == self.localAvId: base.playSfx(self.negBuzzer) return Task.done def hideNumbers(self, task): self.notify.debug('hiding numbers...') for dice in self.diceInstanceList: if dice: dice.removeNode() self.diceInstanceList = [] return Task.done def enterMoveAvatars(self, choiceList, positionList, rewardList): self.notify.debug('in enterMoveAvatars:') tasks = [] self.avatarPositionsCopy = self.avatarPositions.copy() for i in range(0, len(choiceList) // self.numPlayers): startIndex = i * self.numPlayers endIndex = startIndex + self.numPlayers self.choiceList = choiceList[startIndex:endIndex] self.positionList = positionList[startIndex:endIndex] self.rewardList = rewardList[startIndex:endIndex] self.notify.debug(' turn: ' + str(i + 1)) self.notify.debug(' choiceList: ' + str(self.choiceList)) self.notify.debug(' positionList: ' + str(self.positionList)) self.notify.debug(' rewardList: ' + str(self.rewardList)) longestLerpTime = self.getLongestLerpTime(i > 0) self.notify.debug('longestLerpTime: ' + str(longestLerpTime)) if i == 0: snt = Task(self.showNumbers) snt.choiceList = self.choiceList smt = Task(self.showMatches) smt.choiceList = self.choiceList tasks += [snt, Task.pause(0.5), smt] if longestLerpTime > 0.0: self.notify.debug('someone moved...') mat = Task(self.moveAvatars) mat.choiceList = self.choiceList mat.positionList = self.positionList mat.rewardList = self.rewardList mat.name = 'moveAvatars' if i == 0: tasks += [Task.pause(0.75), mat, Task.pause(0.75), Task(self.hideNumbers), Task.pause(longestLerpTime - 0.5)] else: mat.chance = 1 tasks += [mat, Task.pause(longestLerpTime)] tasks += self.showChanceRewards() else: self.notify.debug('no one moved...') tasks += [Task.pause(1.0), Task(self.hideNumbers)] self.notify.debug('task list : ' + str(tasks)) wdt = Task(self.walkDone) wdt.name = 'walk done' tasks.append(wdt) moveTask = Task.sequence(*tasks) taskMgr.add(moveTask, 'moveAvatars') def walkDone(self, task): self.choiceList = [] self.positionList = [] if self.anyAvatarWon(): self.gameFSM.request('winMovie') else: self.gameFSM.request('inputChoice') return Task.done def getLongestLerpTime(self, afterFirst): self.notify.debug('afterFirst: ' + str(afterFirst)) longestTime = 0.0 for i in range(len(self.choiceList)): freq = self.choiceList.count(self.choiceList[i]) if afterFirst or freq == 1: oldPosition = self.avatarPositionsCopy[self.avIdList[i]] newPosition = self.positionList[i] self.avatarPositionsCopy[self.avIdList[i]] = newPosition squares_walked = abs(newPosition - oldPosition) longestTime = max(longestTime, self.getWalkDuration(squares_walked)) return longestTime def showChanceRewards(self): tasks = [] for reward in self.rewardList: self.notify.debug('showChanceRewards: reward = ' + str(reward)) index = self.rewardList.index(reward) if reward != -1: self.notify.debug('adding tasks!') hcc = Task(self.hideChanceMarker) hcc.chanceMarkers = self.chanceMarkers hcc.index = index sct = Task(self.showChanceCard) sct.chanceCard = self.chanceCard sct.cardSound = self.cardSound stt = Task(self.showChanceCardText) rewardEntry = RaceGameGlobals.ChanceRewards[reward] stt.rewardIdx = reward if rewardEntry[0][0] < 0 or rewardEntry[0][1] > 0: stt.sound = self.negBuzzer else: stt.sound = self.posBuzzer stt.picker = self.avIdList[index] rct = Task(self.resetChanceCard) task = Task.sequence(hcc, sct, Task.pause(1.0), stt, Task.pause(3.0), rct, Task.pause(0.25)) tasks.append(task) return tasks def showChanceCard(self, task): base.playSfx(task.cardSound) self.chanceCard.reparentTo(render) self.chanceCard.lerpPosHpr(19.62, 13.41, 13.14, 270, 0, -85.24, 1.0, other=camera, task='cardLerp') return Task.done def hideChanceMarker(self, task): task.chanceMarkers[task.index].reparentTo(hidden) return Task.done def showChanceCardText(self, task): self.notify.debug('showing chance reward: ' + str(task.rewardIdx)) name = self.getAvatar(task.picker).getName() rewardEntry = RaceGameGlobals.ChanceRewards[task.rewardIdx] cardText = '' if rewardEntry[1] != -1: rewardstr_fmt = TTLocalizer.RaceGameCardText if rewardEntry[2] > 0: rewardstr_fmt = TTLocalizer.RaceGameCardTextBeans cardText = rewardstr_fmt % {'name': name, 'reward': rewardEntry[1]} else: rewardstr_fmt = TTLocalizer.RaceGameCardTextHi1 cardText = rewardstr_fmt % {'name': name} base.playSfx(task.sound) self.chanceCardText.setText(cardText) self.chanceCardText.show() return Task.done def resetChanceCard(self, task): self.chanceCardText.hide() self.chanceCard.reparentTo(hidden) self.chanceCard.setPosHpr(0, 0, 0, 0, 0, 0) return Task.done def moveCamera(self): bestPosIdx = list(self.avatarPositions.values())[0] best_lane = 0 cur_lane = 0 for pos in list(self.avatarPositions.values()): if pos > bestPosIdx: bestPosIdx = pos best_lane = cur_lane cur_lane = cur_lane + 1 bestPosIdx = min(RaceGameGlobals.NumberToWin, bestPosIdx) localToonPosition = self.avatarPositions[self.localAvId] savedCamPos = camera.getPos() savedCamHpr = camera.getHpr() pos1_idx = min(RaceGameGlobals.NumberToWin - 4, localToonPosition) pos1 = self.posHprArray[self.localAvLane][pos1_idx] bestPosLookAtIdx = bestPosIdx + 1 localToonLookAtIdx = localToonPosition + 4 if localToonLookAtIdx >= bestPosLookAtIdx: pos2_idx = localToonLookAtIdx pos2_idx = min(RaceGameGlobals.NumberToWin, pos2_idx) pos2 = self.posHprArray[self.localAvLane][pos2_idx] else: pos2_idx = bestPosLookAtIdx pos2_idx = min(RaceGameGlobals.NumberToWin, pos2_idx) pos2 = self.posHprArray[best_lane][pos2_idx] posDeltaVecX = pos2[0] - pos1[0] posDeltaVecY = pos2[1] - pos1[1] DistanceMultiplier = 0.8 camposX = pos2[0] + DistanceMultiplier * posDeltaVecX camposY = pos2[1] + DistanceMultiplier * posDeltaVecY race_fraction = bestPosIdx / float(RaceGameGlobals.NumberToWin) CamHeight = 10.0 * race_fraction + (1.0 - race_fraction) * 22.0 CamPos = Vec3(camposX, camposY, pos2[2] + CamHeight) camera.setPos(CamPos) camera_lookat_idx = min(RaceGameGlobals.NumberToWin - 6, localToonPosition) posLookAt = self.posHprArray[self.localAvLane][camera_lookat_idx] camera.lookAt(posLookAt[0], posLookAt[1], posLookAt[2]) CamQuat = Quat() CamQuat.setHpr(camera.getHpr()) camera.setPos(savedCamPos) camera.setHpr(savedCamHpr) camera.posQuatInterval(0.75, CamPos, CamQuat).start() def getWalkDuration(self, squares_walked): walkDuration = abs(squares_walked / 1.2) if squares_walked > 4: walkDuration = walkDuration * 0.3 return walkDuration def moveAvatars(self, task): self.notify.debug('In moveAvatars: ') self.notify.debug(' choiceList: ' + str(task.choiceList)) self.notify.debug(' positionList: ' + str(task.positionList)) self.notify.debug(' rewardList: ' + str(task.rewardList)) for i in range(len(self.choiceList)): avId = self.avIdList[i] choice = task.choiceList[i] position = task.positionList[i] chance = max(0, hasattr(task, 'chance')) if choice != 0: oldPosition = self.avatarPositions[avId] self.avatarPositions[avId] = position self.moveCamera() if not chance and task.choiceList.count(choice) != 1: self.notify.debug('duplicate choice!') else: avatar = self.getAvatar(avId) if avatar: squares_walked = abs(position - oldPosition) if squares_walked > 4: self.notify.debug('running') avatar.setPlayRate(1.0, 'run') self.runInPlace(avatar, i, oldPosition, position, self.getWalkDuration(squares_walked)) else: if choice > 0: self.notify.debug('walking forwards') avatar.setPlayRate(1.0, 'walk') else: self.notify.debug('walking backwards') avatar.setPlayRate(-1.0, 'walk') self.walkInPlace(avatar, i, position, self.getWalkDuration(squares_walked)) return Task.done def exitMoveAvatars(self): self.notify.debug('In exitMoveAvatars: removing hooks') taskMgr.remove('moveAvatars') return None def gameOverCallback(self, task): self.gameOver() return Task.done def enterWinMovie(self): self.notify.debug('enterWinMovie') if self.localToonWon(): base.playSfx(self.winSting) else: base.playSfx(self.loseSting) for avId in self.avIdList: avPosition = self.avatarPositions[avId] if avPosition >= RaceGameGlobals.NumberToWin: avatar = self.getAvatar(avId) if avatar: lane = str(self.avIdList.index(avId)) taskMgr.remove('runAvatar-' + lane) taskMgr.remove('walkAvatar-' + lane) avatar.setAnimState('jump', 1.0) taskMgr.doMethodLater(4.0, self.gameOverCallback, 'playMovie') def exitWinMovie(self): taskMgr.remove('playMovie') self.winSting.stop() self.loseSting.stop() def enterCleanup(self): self.notify.debug('enterCleanup') def exitCleanup(self): pass def positionInPlace(self, avatar, lane, place): place = min(place, len(self.posHprArray[lane]) - 1) posH = self.posHprArray[lane][place] avatar.setPosHpr(self.raceBoard, posH[0], posH[1], posH[2], posH[3], 0, 0) def walkInPlace(self, avatar, lane, place, time): place = min(place, len(self.posHprArray[lane]) - 1) posH = self.posHprArray[lane][place] def stopWalk(raceBoard = self.raceBoard, posH = posH): avatar.setAnimState('neutral', 1) if raceBoard.isEmpty(): avatar.setPosHpr(0, 0, 0, 0, 0, 0) else: avatar.setPosHpr(raceBoard, posH[0], posH[1], posH[2], posH[3], 0, 0) posQuat = Quat() posQuat.setHpr((posH[3], 0, 0)) walkSeq = Sequence(Func(avatar.setAnimState, 'walk', 1), avatar.posQuatInterval(time, posH[:3], posQuat, other=self.raceBoard), Func(stopWalk)) walkSeq.start() def runInPlace(self, avatar, lane, currentPlace, newPlace, time): place = min(newPlace, len(self.posHprArray[lane]) - 1) step = (place - currentPlace) // 3 pos1 = self.posHprArray[lane][currentPlace + step] pos2 = self.posHprArray[lane][currentPlace + 2 * step] pos3 = self.posHprArray[lane][place] def startRun(task): task.avatar.setAnimState('run', 1) return Task.done startRunTask = Task(startRun, 'startRun-' + str(lane)) startRunTask.avatar = avatar def stopRun(task, raceBoard = self.raceBoard, pos3 = pos3): task.avatar.setAnimState('neutral', 1) task.avatar.setPosHpr(raceBoard, pos3[0], pos3[1], pos3[2], pos3[3], 0, 0) return Task.done stopRunTask = Task(stopRun, 'stopRun-' + str(lane)) stopRunTask.avatar = avatar runTask = Task.sequence(startRunTask, avatar.lerpPosHpr(pos1[0], pos1[1], pos1[2], pos1[3], 0, 0, time / 3.0, other=self.raceBoard), avatar.lerpPosHpr(pos2[0], pos2[1], pos2[2], pos2[3], 0, 0, time / 3.0, other=self.raceBoard), avatar.lerpPosHpr(pos3[0], pos3[1], pos3[2], pos3[3], 0, 0, time / 3.0, other=self.raceBoard), stopRunTask) taskMgr.add(runTask, 'runAvatar-' + str(lane)) def setAvatarChoice(self, choice): self.notify.error('setAvatarChoice should not be called on the client') def setAvatarChose(self, avId): if not self.hasLocalToon: return self.notify.debug('setAvatarChose: avatar: ' + str(avId) + ' choose a number') def setChancePositions(self, positions): if not self.hasLocalToon: return row = 0 for pos in positions: marker = self.chanceMarker.copyTo(render) posHpr = self.posHprArray[row][pos] marker.setPosHpr(self.raceBoard, posHpr[0], posHpr[1], posHpr[2], posHpr[3] + 180, 0, 0.025) marker.setScale(0.7) marker.setDepthOffset(1) self.chanceMarkers.append(marker) row += 1 def setServerChoices(self, choices, positions, rewards): if not self.hasLocalToon: return for i in range(len(positions)): if positions[i] > RaceGameGlobals.NumberToWin: positions[i] = RaceGameGlobals.NumberToWin if positions[i] < 0: positions[i] = 0 self.notify.debug('setServerChoices: %s positions: %s rewards: %s ' % (choices, positions, rewards)) self.gameFSM.request('moveAvatars', [choices, positions, rewards]) def resetPositions(self): for avId in self.avIdList: self.avatarPositions[avId] = 0