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 import ArrowKeys import random from toontown.toonbase import ToontownGlobals import string from toontown.toonbase import TTLocalizer import TugOfWarGameGlobals from direct.showutil import Rope from toontown.effects import Splash from toontown.effects import Ripples from toontown.toonbase import TTLocalizer import MinigamePowerMeter from direct.task.Task import Task class DistributedTugOfWarGame(DistributedMinigame): bgm = 'phase_4/audio/bgm/MG_tug_o_war.mid' 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.wav') self.sndHitWater = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_splash.mp3') self.whistleSound = base.loader.loadSfx('phase_4/audio/sfx/AA_sound_whistle.mp3') self.music = base.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 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 self.dropShadowDict.has_key(avId): self.dropShadowDict[avId].reparentTo(hidden) if self.dropShadowDict.has_key(self.suitId): 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 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