from pandac.PandaModules import * from toontown.toonbase.ToonBaseGlobal 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 toontown.toonbase import ToontownTimer from toontown.toon import ToonHead from toontown.suit import SuitDNA from toontown.suit import Suit from toontown.char import Char from . import ArrowKeys import random from toontown.toonbase import ToontownGlobals import string from toontown.toonbase import TTLocalizer from . import TugOfWarGameGlobals from direct.showutil import Rope from toontown.effects import Splash from toontown.effects import Ripples from toontown.toonbase import TTLocalizer from . import MinigamePowerMeter from direct.task.Task import Task class DistributedTugOfWarGame(DistributedMinigame): bgm = 'phase_4/audio/bgm/MG_tug_o_war.ogg' toonAnimNames = ['neutral', 'tug-o-war', 'slip-forward', 'slip-backward', 'victory', 'sad-neutral'] suitAnimNames = ['neutral', 'tug-o-war', 'slip-forward', 'slip-backward', 'flail', 'victory'] UPDATE_TIMER_TASK = 'TugOfWarGameUpdateTimerTask' UPDATE_KEY_PRESS_RATE_TASK = 'TugOfWarGameUpdateKeyPressRateTask' UPDATE_ROPE_TASK = 'TugOfWarGameUpdateRopeTask' H_TO_L = 0 L_TO_H = 1 def __init__(self, cr): DistributedMinigame.__init__(self, cr) self.gameFSM = ClassicFSM.ClassicFSM('DistributedTugOfWarGame', [State.State('off', self.enterOff, self.exitOff, ['waitForGoSignal']), State.State('waitForGoSignal', self.enterWaitForGoSignal, self.exitWaitForGoSignal, ['tug', 'cleanup']), State.State('tug', self.enterTug, self.exitTug, ['gameDone', 'cleanup']), State.State('gameDone', self.enterGameDone, self.exitGameDone, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) self.gameType = TugOfWarGameGlobals.TOON_VS_TOON self.suit = None self.suitId = 666 self.suitType = 'f' self.suitLevel = 1 self.sides = {} self.avList = [[], []] self.buttons = [0, 1] self.mouseMode = 0 self.mouseSide = 0 self.fallenList = [] self.handycap = 2.0 self.advantage = 1.0 self.tugRopes = [] self.ropePts = [] self.ropeTex = [] self.rightHandDict = {} self.posDict = {} self.hprDict = {} self.offsetDict = {} self.pullingDict = {} self.dropShadowDict = {} self.arrowKeys = None self.keyTTL = [] self.idealRate = 2.0 self.idealForce = 0.0 self.keyRate = 0 self.allOutMode = 0 self.rateMatchAward = 0 self.targetRateList = [[8, 6], [5, 7], [6, 8], [6, 10], [7, 11], [8, 12]] self.nextRateIndex = 0 self.drinkPositions = [] for k in range(4): self.drinkPositions.append(VBase3(-.2 + 0.2 * k, 16 + 2 * k, 0.0)) self.rng = RandomNumGen.RandomNumGen(1000) self.introTrack = None self.showTrack = None self.setupTrack = None self.animTracks = {} self.randomNumGen = None return def getTitle(self): return TTLocalizer.TugOfWarGameTitle def getInstructions(self): return TTLocalizer.TugOfWarInstructions def getMaxDuration(self): return TugOfWarGameGlobals.GAME_DURATION def load(self): self.notify.debug('load') DistributedMinigame.load(self) self.timer = ToontownTimer.ToontownTimer() self.timer.posInTopRightCorner() self.timer.hide() self.room = loader.loadModel('phase_4/models/minigames/tug_of_war_dock') self.room.reparentTo(hidden) ropeModel = loader.loadModel('phase_4/models/minigames/tug_of_war_rope') self.ropeTexture = ropeModel.findTexture('*') ropeModel.removeNode() self.sky = loader.loadModel('phase_3.5/models/props/TT_sky') self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow') self.correctSound = base.loader.loadSfx('phase_4/audio/sfx/MG_pos_buzzer.ogg') self.sndHitWater = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_splash.ogg') self.whistleSound = base.loader.loadSfx('phase_4/audio/sfx/AA_sound_whistle.ogg') self.music = base.loader.loadMusic(self.bgm) self.roundText = DirectLabel(text=' ', text_fg=(0, 1, 0, 1), frameColor=(1, 1, 1, 0), text_font=ToontownGlobals.getSignFont(), pos=(0.014, 0, -.84), scale=0.2) self.powerMeter = MinigamePowerMeter.MinigamePowerMeter(17) self.powerMeter.reparentTo(aspect2d) self.powerMeter.setPos(0, 0, 0.4) self.powerMeter.setPower(8) self.powerMeter.setTarget(8) self.arrows = [None] * 2 for x in range(len(self.arrows)): self.arrows[x] = loader.loadModel('phase_3/models/props/arrow') self.arrows[x].reparentTo(self.powerMeter) self.arrows[x].hide() self.arrows[x].setScale(0.2 - 0.4 * x, 0.2, 0.2) self.arrows[x].setPos(0.12 - 0.24 * x, 0, -.26) self.disableArrow(self.arrows[x]) self.splash = Splash.Splash(render) self.suitSplash = Splash.Splash(render) self.ripples = Ripples.Ripples(render) self.suitRipples = Ripples.Ripples(render) return def toggleMouseMode(self, param): self.mouseMode = not self.mouseMode if self.mouseMode: mpos = param.getMouse() if mpos[0] < 0: self.hilightArrow(self.arrows[1]) else: self.hilightArrow(self.arrows[0]) self.__spawnMouseSpeedTask() else: self.__releaseHandler(0) self.__releaseHandler(1) self.__killMouseSpeedTask() def unload(self): self.notify.debug('unload') DistributedMinigame.unload(self) del self.lt self.timer.destroy() del self.timer self.room.removeNode() del self.room self.sky.removeNode() del self.sky del self.dropShadowDict self.dropShadow.removeNode() del self.dropShadow del self.correctSound del self.sndHitWater del self.whistleSound del self.music self.roundText.destroy() del self.roundText if self.powerMeter: self.powerMeter.destroy() del self.powerMeter for x in self.arrows: if x: x.removeNode() del x del self.arrows self.splash.destroy() del self.splash self.suitSplash.destroy() del self.suitSplash if self.ripples != None: self.ripples.stop() self.ripples.detachNode() del self.ripples if self.suitRipples != None: self.suitRipples.stop() self.suitRipples.detachNode() del self.suitRipples for x in self.avList: del x del self.avList for x in self.tugRopes: if x != None: x.detachNode() del x del self.tugRopes for x in self.ropePts: if x: for t in x: del t del x del self.ropePts for x in self.ropeTex: if x: for t in x: t.destroy() del t del x del self.ropeTex del self.posDict del self.hprDict self.removeChildGameFSM(self.gameFSM) del self.gameFSM if self.suit: self.suit.delete() del self.suit del self.sides del self.buttons del self.pullingDict del self.rightHandDict for x in self.drinkPositions: del x del self.drinkPositions del self.offsetDict del self.keyTTL del self.rng return def onstage(self): self.notify.debug('onstage') DistributedMinigame.onstage(self) self.lt = base.localAvatar NametagGlobals.setGlobalNametagScale(1) self.arrowKeys = ArrowKeys.ArrowKeys() self.room.reparentTo(render) self.room.setPosHpr(0.0, 18.39, -ToontownGlobals.FloorOffset, 0.0, 0.0, 0.0) self.room.setScale(0.4) self.sky.setZ(-5) self.sky.reparentTo(render) self.dropShadow.setColor(0, 0, 0, 0.5) camera.reparentTo(render) camera.setPosHpr(-11.4427, 9.03559, 2.80094, -49.104, -0.89, 0) self.dropShadow.setBin('fixed', 0, 1) self.splash.reparentTo(render) self.suitSplash.reparentTo(render) base.playMusic(self.music, looping=1, volume=1) for x in range(len(self.arrows)): self.arrows[x].show() for avId in self.avIdList: self.pullingDict[avId] = 0 def offstage(self): self.notify.debug('offstage') DistributedMinigame.offstage(self) self.music.stop() if self.introTrack: self.introTrack.finish() del self.introTrack self.introTrack = None for track in list(self.animTracks.values()): if track: track.finish() del track self.animTracks = {} if self.showTrack: self.showTrack.finish() del self.showTrack self.showTrack = None if self.setupTrack: self.setupTrack.finish() del self.setupTrack self.setupTrack = None base.camLens.setFov(ToontownGlobals.DefaultCameraFov) base.camLens.setNearFar(ToontownGlobals.DefaultCameraNear, ToontownGlobals.DefaultCameraFar) NametagGlobals.setGlobalNametagScale(1.0) if self.arrowKeys: self.arrowKeys.setPressHandlers(self.arrowKeys.NULL_HANDLERS) self.arrowKeys.setReleaseHandlers(self.arrowKeys.NULL_HANDLERS) self.arrowKeys.destroy() del self.arrowKeys self.arrowKeys = None self.room.reparentTo(hidden) self.sky.reparentTo(hidden) self.splash.reparentTo(hidden) self.splash.stop() self.suitSplash.reparentTo(hidden) self.suitSplash.stop() self.ripples.reparentTo(hidden) self.ripples.stop() self.hideControls() self.roundText.hide() for avId in self.avIdList: av = self.getAvatar(avId) if av: av.loop('neutral') av.resetLOD() av.dropShadow.show() for x in self.tugRopes: if x != None: x.reparentTo(hidden) if self.suit: self.suit.reparentTo(hidden) for avId in self.avIdList: if avId in self.dropShadowDict: self.dropShadowDict[avId].reparentTo(hidden) if self.suitId in self.dropShadowDict: self.dropShadowDict[self.suitId].reparentTo(hidden) return def initCamera(self): birdseyePosHpr = [1.95461, 18.4891, 38.4646, 1.18185, -87.5308, 0] introPosHpr = [None] * 2 introPosHpr[0] = [VBase3(-11.4427, 9.03559, 2.80094), VBase3(-49.104, -0.732374, 0)] introPosHpr[1] = [VBase3(16.9291, 13.9302, 2.64282), VBase3(66.9685, -6.195, 0)] gameCamHpr = VBase3(-1.13, 1.042, 0) gameCamPos = VBase3(0, 1.0838, 2.745) camera.reparentTo(render) camera.setPosHpr(introPosHpr[self.sides[self.localAvId]][0], introPosHpr[self.sides[self.localAvId]][1]) lerpDur = 8 self.introTrack = LerpPosHprInterval(camera, lerpDur, pos=gameCamPos, hpr=gameCamHpr, blendType='easeInOut', name=self.uniqueName('introLerpCameraPos')) self.introTrack.start() base.camLens.setFov(60 + 2 * self.numPlayers) base.camLens.setFar(450.0) return def sendGameType(self, index, suit): if not self.hasLocalToon: return self.gameType = index self.suitLevel = suit if suit == 1: self.suitType = 'pp' elif suit == 2: self.suitType = 'dt' elif suit == 3: self.suitType = 'gh' elif suit == 4: self.suitType = 'cr' def setGameReady(self): if not self.hasLocalToon: return self.notify.debug('setGameReady') if DistributedMinigame.setGameReady(self): return self.initToons() self.createSuits() self.calculatePositions() self.initHandycaps() self.initRopes() self.initCamera() self.animTracks = {} for avId in self.avIdList: self.animTracks[avId] = None self.animTracks[self.suitId] = None self.showTrack = None self.setupTrack = None self.__initGameVars() return def hideControls(self): for x in range(len(self.arrows)): self.arrows[x].hide() for rope in self.tugRopes: if rope != None: rope.reparentTo(hidden) for tex in self.ropeTex: if tex != None: for texi in tex: if texi: texi.reparentTo(hidden) if self.powerMeter != None: self.powerMeter.unbind(DGG.B1PRESS) self.powerMeter.unbind(DGG.B1RELEASE) self.powerMeter.hide() return def setUpRopes(self, notTaut): if self.numPlayers == 1: suitRightHand = self.suit.getRightHand() toonRightHand = self.rightHandDict[self.avIdList[0]] if notTaut: self.tugRopes[0].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) else: midPt = (suitRightHand.getPos() - toonRightHand.getPos()) / 2.0 self.tugRopes[0].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) self.tugRopes[0].reparentTo(render) elif self.numPlayers == 2: if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) suitRightHand = self.suit.getRightHand() toonRightHand = self.rightHandDict[self.avIdList[1]] if notTaut: self.tugRopes[1].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) else: midPt = (suitRightHand.getPos() - toonRightHand.getPos()) / 2.0 self.tugRopes[1].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) self.tugRopes[0].reparentTo(render) self.tugRopes[1].reparentTo(render) else: if notTaut: self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (render, (0, 18, -1)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) else: self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) self.tugRopes[0].reparentTo(render) elif self.numPlayers == 3: if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) suitRightHand = self.suit.getRightHand() toonRightHand = self.rightHandDict[self.avIdList[2]] if notTaut: self.tugRopes[2].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) else: midPt = (suitRightHand.getPos() - toonRightHand.getPos()) / 2.0 self.tugRopes[2].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) self.tugRopes[0].reparentTo(render) self.tugRopes[1].reparentTo(render) self.tugRopes[2].reparentTo(render) else: if notTaut: self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (render, (0, 18, -1)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) else: self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) self.tugRopes[0].reparentTo(render) self.tugRopes[1].reparentTo(render) elif self.numPlayers == 4: if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: self.tugRopes[2].setup(3, ((self.rightHandDict[self.avIdList[2]], (0, 0, 0)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0)), (self.rightHandDict[self.avIdList[3]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) suitRightHand = self.suit.getRightHand() toonRightHand = self.rightHandDict[self.avIdList[3]] if notTaut: self.tugRopes[3].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) else: midPt = (suitRightHand.getPos() - toonRightHand.getPos()) / 2.0 self.tugRopes[3].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0, 0, 0, 1, 1, 1]) self.tugRopes[0].reparentTo(render) self.tugRopes[1].reparentTo(render) self.tugRopes[2].reparentTo(render) self.tugRopes[3].reparentTo(render) else: self.tugRopes[2].setup(3, ((self.rightHandDict[self.avIdList[2]], (0, 0, 0)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0)), (self.rightHandDict[self.avIdList[3]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) if notTaut: self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (render, (0, 18, -1)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) else: self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0, 0, 0, 1, 1, 1]) self.tugRopes[0].reparentTo(render) self.tugRopes[1].reparentTo(render) self.tugRopes[2].reparentTo(render) def initToons(self): for avId in self.avIdList: toon = self.getAvatar(avId) if toon: toon.reparentTo(render) toon.useLOD(1000) toon.startBlink() toon.startLookAround() for anim in self.toonAnimNames: toon.pose(anim, 0) toon.pose('tug-o-war', 3) self.rightHandDict[avId] = toon.getRightHands()[0] toon.loop('neutral') toon.dropShadow.hide() self.dropShadowDict[avId] = self.dropShadow.copyTo(hidden) self.dropShadowDict[avId].reparentTo(toon) self.dropShadowDict[avId].setScale(0.35) def calculatePositions(self): hprPositions = [VBase3(240, 0, 0), VBase3(120, 0, 0)] dockPositions = [] for k in range(5): dockPositions.append(VBase3(-9.0 + 1.5 * k, 18, 0.1)) for k in range(5): dockPositions.append(VBase3(3 + 1.5 * k, 18, 0.1)) self.sendUpdate('sendNewAvIdList', [self.avIdList]) if self.numPlayers == 1: if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: self.posDict[self.suitId] = dockPositions[7] self.posDict[self.avIdList[0]] = dockPositions[2] self.hprDict[self.avIdList[0]] = hprPositions[0] else: self.notify.warning("can't play toon vs. toon with one player") elif self.numPlayers == 2: if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: self.arrangeByHeight(self.avIdList, self.H_TO_L, 0, 1) self.posDict[self.suitId] = dockPositions[7] self.posDict[self.avIdList[0]] = dockPositions[1] self.posDict[self.avIdList[1]] = dockPositions[2] self.hprDict[self.avIdList[0]] = hprPositions[0] self.hprDict[self.avIdList[1]] = hprPositions[0] else: self.randomNumGen.shuffle(self.avIdList) self.posDict[self.avIdList[0]] = dockPositions[2] self.posDict[self.avIdList[1]] = dockPositions[7] self.hprDict[self.avIdList[0]] = hprPositions[0] self.hprDict[self.avIdList[1]] = hprPositions[1] elif self.numPlayers == 3: if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: self.arrangeByHeight(self.avIdList, self.H_TO_L, 0, 2) self.posDict[self.suitId] = dockPositions[7] self.posDict[self.avIdList[0]] = dockPositions[0] self.posDict[self.avIdList[1]] = dockPositions[1] self.posDict[self.avIdList[2]] = dockPositions[2] self.hprDict[self.avIdList[0]] = hprPositions[0] self.hprDict[self.avIdList[1]] = hprPositions[0] self.hprDict[self.avIdList[2]] = hprPositions[0] else: self.randomNumGen.shuffle(self.avIdList) self.arrangeByHeight(self.avIdList, self.H_TO_L, 0, 1) self.posDict[self.avIdList[0]] = dockPositions[1] self.posDict[self.avIdList[1]] = dockPositions[2] self.posDict[self.avIdList[2]] = dockPositions[7] self.hprDict[self.avIdList[0]] = hprPositions[0] self.hprDict[self.avIdList[1]] = hprPositions[0] self.hprDict[self.avIdList[2]] = hprPositions[1] elif self.numPlayers == 4: if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: self.arrangeByHeight(self.avIdList, self.H_TO_L, 0, 3) self.posDict[self.suitId] = dockPositions[6] self.posDict[self.avIdList[0]] = dockPositions[0] self.posDict[self.avIdList[1]] = dockPositions[1] self.posDict[self.avIdList[2]] = dockPositions[2] self.posDict[self.avIdList[3]] = dockPositions[3] self.hprDict[self.avIdList[0]] = hprPositions[0] self.hprDict[self.avIdList[1]] = hprPositions[0] self.hprDict[self.avIdList[2]] = hprPositions[0] self.hprDict[self.avIdList[3]] = hprPositions[0] else: self.randomNumGen.shuffle(self.avIdList) self.arrangeByHeight(self.avIdList, self.H_TO_L, 0, 1) self.arrangeByHeight(self.avIdList, self.L_TO_H, 2, 3) self.posDict[self.avIdList[0]] = dockPositions[1] self.posDict[self.avIdList[1]] = dockPositions[2] self.posDict[self.avIdList[2]] = dockPositions[7] self.posDict[self.avIdList[3]] = dockPositions[8] self.hprDict[self.avIdList[0]] = hprPositions[0] self.hprDict[self.avIdList[1]] = hprPositions[0] self.hprDict[self.avIdList[2]] = hprPositions[1] self.hprDict[self.avIdList[3]] = hprPositions[1] for x in self.avIdList: self.offsetDict[x] = 0 if self.posDict[x][0] < 0: self.sides[x] = 0 self.avList[0].append(x) else: self.sides[x] = 1 self.avList[1].append(x) for avId in self.avIdList: toon = self.getAvatar(avId) toon.setPos(self.posDict[avId]) toon.setHpr(self.hprDict[avId]) def arrangeByHeight(self, avIdList, order, iStart, iFin): for i in range(iStart, iFin + 1): for j in range(i + 1, iFin + 1): if order == self.H_TO_L and self.rightHandDict[avIdList[i]].getZ() < self.rightHandDict[avIdList[j]].getZ() or order == self.L_TO_H and self.rightHandDict[avIdList[i]].getZ() > self.rightHandDict[avIdList[j]].getZ(): temp = avIdList[i] avIdList[i] = avIdList[j] avIdList[j] = temp def disableArrow(self, a): a.setColor(1, 0, 0, 0.3) def enableArrow(self, a): a.setColor(1, 0, 0, 1) def hilightArrow(self, a): a.setColor(1, 0.7, 0, 1) def unhilightArrow(self, a): self.enableArrow(a) def handleDisabledAvatar(self, avId): self.notify.debug('handleDisabledAvatar') self.notify.debug('avatar ' + str(avId) + ' disabled') DistributedMinigame.handleDisabledAvatar(self, avId) def __playing(self): return self.gameFSM.getCurrentState() != self.gameFSM.getFinalState() def setGameStart(self, timestamp): if not self.hasLocalToon: return self.notify.debug('setGameStart') if not self.__playing(): return DistributedMinigame.setGameStart(self, timestamp) self.gameFSM.request('waitForGoSignal') def __initGameVars(self): pass def makeToonLookatCamera(self, toon): toon.headsUp(camera) def setText(self, t, newtext): t['text'] = newtext def setTextFG(self, t, fg): t['text_fg'] = fg def enterOff(self): self.notify.debug('enterOff') def exitOff(self): pass def enterWaitForGoSignal(self): self.notify.debug('enterWaitForGoSignal') self.powerMeter.show() self.sendUpdate('reportPlayerReady', [self.sides[self.localAvId]]) self.roundText.show() taskMgr.doMethodLater(TugOfWarGameGlobals.WAIT_FOR_GO_TIMEOUT, self.waitForGoTimeoutTask, self.taskName('wait-for-go-timeout')) def exitWaitForGoSignal(self): taskMgr.remove(self.taskName('wait-for-go-timeout')) def enterTug(self): self.notify.debug('enterTug') self.__spawnUpdateIdealRateTask() self.__spawnUpdateTimerTask() self.__spawnUpdateKeyPressRateTask() taskMgr.doMethodLater(TugOfWarGameGlobals.TUG_TIMEOUT, self.tugTimeoutTask, self.taskName('tug-timeout')) if self.suit: self.suit.loop('tug-o-war') def exitTug(self): self.notify.debug('exitTug') if self.suit: self.suit.loop('neutral') self.timer.stop() self.timer.hide() taskMgr.remove(self.taskName('tug-timeout')) def enterGameDone(self): pass def exitGameDone(self): pass def enterCleanup(self): self.notify.debug('enterCleanup') self.__killUpdateIdealRateTask() self.__killUpdateTimerTask() self.__killUpdateKeyPressRateTask() self.__killUpdateRopeTask() def exitCleanup(self): pass def __gameTimerExpired(self): self.notify.debug('game timer expired') if self.arrowKeys: self.arrowKeys.setPressHandlers(self.arrowKeys.NULL_HANDLERS) self.arrowKeys.setReleaseHandlers(self.arrowKeys.NULL_HANDLERS) def __pressHandler(self, index): self.notify.debug('pressHandler') if index == self.buttons[0]: self.hilightArrow(self.arrows[index]) self.keyTTL.insert(0, 1.0) self.buttons.reverse() def __releaseHandler(self, index): self.notify.debug('releaseHandler') if index in self.buttons: self.unhilightArrow(self.arrows[index]) def __updateKeyPressRateTask(self, task): if self.gameFSM.getCurrentState().getName() != 'tug': return Task.done for i in range(len(self.keyTTL)): self.keyTTL[i] -= 0.1 for i in range(len(self.keyTTL)): if self.keyTTL[i] <= 0: a = self.keyTTL[0:i] del self.keyTTL self.keyTTL = a break self.keyRate = len(self.keyTTL) if self.keyRate == self.idealRate or self.keyRate == self.idealRate + 1: self.rateMatchAward += 0.3 else: self.rateMatchAward = 0 self.__spawnUpdateKeyPressRateTask() return Task.done def __updateTimerTask(self, task): if self.gameFSM.getCurrentState().getName() != 'tug': return Task.done self.currentForce = self.computeForce(self.keyRate) self.sendUpdate('reportCurrentKeyRate', [self.keyRate, self.currentForce]) self.setSpeedGauge() self.setAnimState(self.localAvId, self.keyRate) self.__spawnUpdateTimerTask() return Task.done def __spawnUpdateTimerTask(self): taskMgr.remove(self.taskName(self.UPDATE_TIMER_TASK)) taskMgr.doMethodLater(TugOfWarGameGlobals.SEND_UPDATE, self.__updateTimerTask, self.taskName(self.UPDATE_TIMER_TASK)) def __killUpdateTimerTask(self): taskMgr.remove(self.taskName(self.UPDATE_TIMER_TASK)) def __spawnUpdateKeyPressRateTask(self): taskMgr.remove(self.taskName(self.UPDATE_KEY_PRESS_RATE_TASK)) taskMgr.doMethodLater(0.1, self.__updateKeyPressRateTask, self.taskName(self.UPDATE_KEY_PRESS_RATE_TASK)) def __killUpdateKeyPressRateTask(self): taskMgr.remove(self.taskName(self.UPDATE_KEY_PRESS_RATE_TASK)) def __spawnUpdateIdealRateTask(self): self.idealRate = self.targetRateList[self.nextRateIndex][1] self.idealForce = self.advantage * (4 + 0.4 * self.idealRate) taskMgr.doMethodLater(self.targetRateList[self.nextRateIndex][0], self.__updateIdealRateTask, self.taskName('targetRateTimer')) def __updateIdealRateTask(self, task): self.nextRateIndex = self.nextRateIndex + 1 if self.nextRateIndex < len(self.targetRateList): if self.nextRateIndex == len(self.targetRateList) - 1: self.allOutMode = 1 self.idealRate = self.targetRateList[self.nextRateIndex][1] self.idealForce = self.advantage * (4 + 0.4 * self.idealRate) taskMgr.doMethodLater(self.targetRateList[self.nextRateIndex][0], self.__updateIdealRateTask, self.taskName('targetRateTimer')) return Task.done def __killUpdateIdealRateTask(self): taskMgr.remove(self.taskName('targetRateTimer')) def sendGoSignal(self, index): if not self.hasLocalToon: return self.notify.debug('sendGoSignal') self.buttons = index self.setupTrack = None self.showTrack = None def startTimer(self = self): self.currentStartTime = int(globalClock.getFrameTime() * 1000) time = 10 self.timer.show() self.timer.setTime(TugOfWarGameGlobals.GAME_DURATION) self.timer.countdown(TugOfWarGameGlobals.GAME_DURATION, self.__gameTimerExpired) def enableKeys(self = self): def keyPress(self, index): self.__pressHandler(index) def keyRelease(self, index): self.__releaseHandler(index) self.arrowKeys.setPressHandlers([lambda self = self, keyPress = keyPress: keyPress(self, 2), lambda self = self, keyPress = keyPress: keyPress(self, 3), lambda self = self, keyPress = keyPress: keyPress(self, 1), lambda self = self, keyPress = keyPress: keyPress(self, 0)]) self.arrowKeys.setReleaseHandlers([lambda self = self, keyRelease = keyRelease: keyRelease(self, 2), lambda self = self, keyRelease = keyRelease: keyRelease(self, 3), lambda self = self, keyRelease = keyRelease: keyRelease(self, 1), lambda self = self, keyRelease = keyRelease: keyRelease(self, 0)]) for x in index: self.enableArrow(self.arrows[x]) if self.introTrack != None: self.introTrack.finish() self.introTrack = None self.setupTrack = Sequence(Func(self.setText, self.roundText, TTLocalizer.TugOfWarGameReady), Wait(1.5), Func(base.playSfx, self.whistleSound), Func(self.setText, self.roundText, TTLocalizer.TugOfWarGameGo), Func(self.roundText.setScale, 0.3), Wait(1.5), Func(startTimer), Func(enableKeys), Func(self.gameFSM.request, 'tug'), Func(self.setText, self.roundText, ' '), Func(self.roundText.setScale, 0.2)) self.setupTrack.start() return def sendStopSignal(self, winners, losers, tieers): if not self.hasLocalToon: return self.notify.debug('sendStopSignal') self.gameFSM.request('gameDone') self.hideControls() reactSeq = Sequence() exitSeq = Sequence() suitSlipTime = 0 if self.gameFSM.getCurrentState().getName() == 'cleanup' or not self.randomNumGen: return if self.suit: if self.suitId in winners: newPos = VBase3(2.65, 18, 0.1) randInt = self.randomNumGen.randrange(0, 10) oopsTrack = Wait(0) if randInt < 3: suitSlipTime = 2.2 waterPos = VBase3(0, 16, -5) newPos -= VBase3(0.4, 0, 0) self.suitSplash.stop() self.suitSplash.setPos(waterPos[0], waterPos[1], -1.8) self.suitSplash.setScale(3.5, 3.5, 1) self.suitRipples.setPos(waterPos[0], waterPos[1], -1.7) self.suitRipples.setScale(1, 1, 1) startHpr = self.suit.getHpr() destHpr = startHpr + VBase3(0, 0, -30) oopsTrack = Sequence(Parallel(Func(self.suit.play, 'flail', None, 26, 38), LerpHprInterval(self.suit, 0.5, destHpr, startHpr=startHpr)), Parallel(Func(self.suit.play, 'slip-forward'), LerpPosInterval(self.suit, duration=1, pos=waterPos), Sequence(Wait(0.55), Func(base.playSfx, self.sndHitWater), Func(self.suitSplash.play), Func(self.ripples.play)))) reactSeq.append(Sequence(Func(self.suit.loop, 'victory'), Wait(2.6), LerpPosInterval(self.suit, duration=2, pos=newPos), oopsTrack, Func(self.suit.loop, 'neutral'))) for avId in self.avIdList: toon = self.getAvatar(avId) toon.loop('neutral') if avId in winners: reactSeq.append(Func(toon.loop, 'victory')) elif avId in losers: reactSeq.append(Func(toon.loop, 'neutral')) else: reactSeq.append(Func(toon.loop, 'neutral')) if self.localAvId in winners: exitSeq.append(Func(self.setText, self.roundText, TTLocalizer.TugOfWarGameEnd)) exitSeq.append(Wait(5.0)) elif self.localAvId in losers: exitSeq.append(Func(self.setText, self.roundText, TTLocalizer.TugOfWarGameEnd)) exitSeq.append(Wait(4.8 + suitSlipTime)) else: exitSeq.append(Func(self.setText, self.roundText, TTLocalizer.TugOfWarGameTie)) exitSeq.append(Wait(2.5)) exitSeq.append(Func(self.gameOver)) self.showTrack = Parallel(reactSeq, exitSeq) for x in list(self.animTracks.values()): if x != None: x.finish() self.showTrack.start() if self.arrowKeys: self.arrowKeys.setPressHandlers(self.arrowKeys.NULL_HANDLERS) self.arrowKeys.setReleaseHandlers(self.arrowKeys.NULL_HANDLERS) return def remoteKeyRateUpdate(self, avId, keyRate): if not self.hasLocalToon: return if avId != self.localAvId: self.setAnimState(avId, keyRate) def sendSuitPosition(self, suitOffset): if not self.hasLocalToon: return if self.gameFSM.getCurrentState().getName() != 'tug': return self.suitOffset = suitOffset self.moveSuits() def sendCurrentPosition(self, avIdList, offsetList): if not self.hasLocalToon: return if self.gameFSM.getCurrentState().getName() != 'tug': return for i in range(len(avIdList)): self.offsetDict[avIdList[i]] = offsetList[i] self.moveToons() self.setUpRopes(0) def createSuits(self): if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: self.suit = Suit.Suit() self.origSuitPosHpr = [VBase3(6.0, 18, 0.1), VBase3(120, 0, 0)] self.suitOffset = 0 d = SuitDNA.SuitDNA() d.newSuit(self.suitType) self.suit.setDNA(d) self.suit.reparentTo(render) self.suit.setPos(self.origSuitPosHpr[0]) self.suit.setHpr(self.origSuitPosHpr[1]) for anim in self.suitAnimNames: self.suit.pose(anim, 0) self.suit.pose('tug-o-war', 0) self.dropShadowDict[self.suitId] = self.dropShadow.copyTo(hidden) self.dropShadowDict[self.suitId].reparentTo(self.suit) self.dropShadowDict[self.suitId].setScale(0.45) def initHandycaps(self): if self.numPlayers == 3 and self.gameType == TugOfWarGameGlobals.TOON_VS_TOON: if len(self.avList[0]) == 1: toon = self.getAvatar(self.avList[0][0]) if self.avList[0][0] == self.localAvId: self.advantage = 2.0 toon.applyCheesyEffect(ToontownGlobals.CEBigHead) elif len(self.avList[1]) == 1: toon = self.getAvatar(self.avList[1][0]) if self.avList[1][0] == self.localAvId: self.advantage = 2.0 toon.applyCheesyEffect(ToontownGlobals.CEBigHead) def setSpeedGauge(self): self.powerMeter.setPower(self.keyRate) self.powerMeter.setTarget(self.idealRate) if not self.allOutMode: self.powerMeter.updateTooSlowTooFast() if not self.allOutMode: index = float(self.currentForce) / self.idealForce bonus = 0.0 if index > 1: bonus = max(1, index - 1) index = 1 color = (0, 0.75 * index + 0.25 * bonus, 0.75 * (1 - index), 0.5) self.powerMeter.setBarColor(color) else: self.powerMeter.setBarColor((0, 1, 0, 0.5)) def setAnimState(self, avId, keyRate): if self.gameFSM.getCurrentState().getName() != 'tug': return toon = self.getAvatar(avId) if keyRate > 0 and self.pullingDict[avId] == 0: toon.loop('tug-o-war') self.pullingDict[avId] = 1 if keyRate <= 0 and self.pullingDict[avId] == 1: toon.pose('tug-o-war', 3) toon.startLookAround() self.pullingDict[avId] = 0 def moveSuits(self): if self.gameType != TugOfWarGameGlobals.TOON_VS_COG: return origPos = self.origSuitPosHpr[0] curPos = self.suit.getPos() newPos = VBase3(origPos[0] + self.suitOffset, curPos[1], curPos[2]) if self.animTracks[self.suitId] != None: if self.animTracks[self.suitId].isPlaying(): self.animTracks[self.suitId].finish() self.checkIfFallen() if self.suitId not in self.fallenList: self.animTracks[self.suitId] = Sequence(LerpPosInterval(self.suit, duration=TugOfWarGameGlobals.SEND_UPDATE, pos=newPos), Func(self.checkIfFallen)) self.animTracks[self.suitId].start() return def moveToons(self): for avId in self.avIdList: if avId not in self.fallenList: toon = self.getAvatar(avId) if toon: origPos = self.posDict[avId] curPos = toon.getPos() newPos = VBase3(origPos[0] + self.offsetDict[avId] / self.handycap, curPos[1], curPos[2]) if self.animTracks[avId] != None: if self.animTracks[avId].isPlaying(): self.animTracks[avId].finish() self.checkIfFallen(avId) if avId not in self.fallenList: self.animTracks[avId] = Sequence(LerpPosInterval(toon, duration=TugOfWarGameGlobals.SEND_UPDATE, pos=newPos), Func(self.checkIfFallen, avId)) self.animTracks[avId].start() return def checkIfFallen(self, avId = None): if avId == None: if self.suitId not in self.fallenList: curPos = self.suit.getPos() if curPos[0] < 0 and curPos[0] > -2 or curPos[0] > 0 and curPos[0] < 2: self.hideControls() self.throwInWater() losingSide = 1 self.sendUpdate('reportEndOfContest', [losingSide]) elif avId not in self.fallenList: toon = self.getAvatar(avId) if toon: curPos = toon.getPos() if curPos[0] < 0 and curPos[0] > -2 or curPos[0] > 0 and curPos[0] < 2: self.hideControls() losingSide = self.sides[avId] for avId in self.avIdList: if self.sides[avId] == losingSide: self.throwInWater(avId) self.sendUpdate('reportEndOfContest', [losingSide]) return def throwInWater(self, avId = None): if avId == None: self.fallenList.append(self.suitId) waterPos = self.drinkPositions.pop() newPos = VBase3(waterPos[0], waterPos[1], waterPos[2] - self.suit.getHeight() / 1.5) self.suit.loop('neutral') self.dropShadowDict[self.suitId].reparentTo(hidden) loser = self.suit animId = self.suitId else: self.fallenList.append(avId) toon = self.getAvatar(avId) waterPos = self.drinkPositions.pop() newPos = VBase3(waterPos[0], waterPos[1], waterPos[2] - toon.getHeight()) toon.loop('neutral') self.dropShadowDict[avId].reparentTo(hidden) loser = toon animId = avId if self.animTracks[animId] != None: if self.animTracks[animId].isPlaying(): self.animTracks[animId].finish() self.splash.setPos(newPos[0], newPos[1], -1.8) self.splash.setScale(2.5, 2.5, 1) self.ripples.setPos(newPos[0], newPos[1], -1.7) self.ripples.setScale(1, 1, 1) self.animTracks[animId] = Sequence(Parallel(ActorInterval(actor=loser, animName='slip-forward', duration=2.0), LerpPosInterval(loser, duration=2.0, pos=newPos), Sequence(Wait(1.0), Parallel(Func(base.playSfx, self.sndHitWater), Func(self.splash.play), Func(self.ripples.play)))), Func(loser.loop, 'neutral')) self.animTracks[animId].start() return def computeForce(self, keyRate): F = 0 if self.allOutMode == 1: F = 0.75 * keyRate else: stdDev = 0.25 * self.idealRate F = self.advantage * (self.rateMatchAward + 4 + 0.4 * self.idealRate) * math.pow(math.e, -math.pow(keyRate - self.idealRate, 2) / (2.0 * math.pow(stdDev, 2))) return F def initRopes(self): if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: numRopes = self.numPlayers else: numRopes = self.numPlayers - 1 for x in range(0, numRopes): rope = Rope.Rope(self.uniqueName('TugRope' + str(x))) if rope.showRope: rope.ropeNode.setRenderMode(RopeNode.RMBillboard) rope.ropeNode.setThickness(0.2) rope.setTexture(self.ropeTexture) rope.ropeNode.setUvMode(RopeNode.UVDistance) rope.ropeNode.setUvDirection(1) rope.setTransparency(1) rope.setColor(0.89, 0.89, 0.6, 1) self.tugRopes.append(rope) self.setUpRopes(1) def __spawnUpdateRopeTask(self): taskMgr.remove(self.taskName(self.UPDATE_ROPE_TASK)) taskMgr.add(self.__updateRopeTask, self.taskName(self.UPDATE_ROPE_TASK)) def __updateRopeTask(self, task): if self.tugRopes != None: for i in range(len(self.tugRopes)): if self.tugRopes[i] != None: self.ropePts[i] = self.tugRopes[i].getPoints(len(self.ropeTex[i])) for j in range(len(self.ropePts[i])): self.ropeTex[i][j].setPos(self.ropePts[i][j]) return Task.cont def __killUpdateRopeTask(self): taskMgr.remove(self.taskName(self.UPDATE_ROPE_TASK)) def tugTimeoutTask(self, task): self.gameOver() return Task.done def waitForGoTimeoutTask(self, task): self.gameOver() return Task.done def __spawnMouseSpeedTask(self): taskMgr.remove(self.taskName('mouseSpeed')) taskMgr.add(self.__mouseSpeedTask, self.taskName('mouseSpeed')) def __killMouseSpeedTask(self): taskMgr.remove(self.taskName('mouseSpeed')) def __mouseSpeedTask(self, task): dx = 0.1 if self.mouseMode: mx = base.mouseWatcherNode.getMouseX() my = base.mouseWatcherNode.getMouseY() if self.mouseSide == 0: if mx > dx: self.mouseSide = 1 self.__releaseHandler(1) self.__pressHandler(0) elif mx > -dx: self.__releaseHandler(1) elif self.mouseSide == 1: if mx < -dx: self.mouseSide = 0 self.__releaseHandler(0) self.__pressHandler(1) elif mx < dx: self.__releaseHandler(0) return Task.cont