fix some broken minigames

This commit is contained in:
Open Toontown 2023-04-29 22:20:11 -04:00
parent 72c6316f6e
commit 03c45eedb0
3 changed files with 437 additions and 307 deletions

View file

@ -1,23 +1,28 @@
from direct.directnotify import DirectNotifyGlobal from panda3d.core import Point3, Quat, rad2Deg, Vec3
from panda3d.core import * from panda3d.otp import Nametag, NametagFloat3d
from toontown.toonbase.ToonBaseGlobal import *
from .DistributedMinigame import * from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.distributed.ClockDelta import * from direct.fsm.ClassicFSM import ClassicFSM
from direct.interval.IntervalGlobal import * from direct.fsm.State import State
from direct.fsm import ClassicFSM, State from direct.gui.DirectGui import DGG, DirectButton, DirectFrame, DirectLabel
from direct.fsm import State from direct.interval.IntervalGlobal import Parallel, Sequence, SoundInterval, Wait
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import ToontownTimer
from direct.task.Task import Task from direct.task.Task import Task
from . import Trajectory from direct.task.TaskManagerGlobal import taskMgr
import math
from toontown.toon import ToonHead from toontown.effects.DustCloud import DustCloud
from toontown.effects import Splash from toontown.effects.Splash import Splash
from toontown.effects import DustCloud from toontown.minigame import CannonGameGlobals
from . import CannonGameGlobals from toontown.minigame import MinigameGlobals
from direct.gui.DirectGui import * from toontown.minigame.DistributedMinigame import DistributedMinigame
from panda3d.core import * from toontown.minigame.Trajectory import Trajectory
from toontown.toon.ToonHead import ToonHead
from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer from toontown.toonbase import TTLocalizer
from toontown.toonbase.ToonBaseGlobal import base
from toontown.toonbase.ToontownTimer import ToontownTimer
import math
LAND_TIME = 2 LAND_TIME = 2
WORLD_SCALE = 2.0 WORLD_SCALE = 2.0
GROUND_SCALE = 1.4 * WORLD_SCALE GROUND_SCALE = 1.4 * WORLD_SCALE
@ -40,8 +45,9 @@ TOWER_X_RANGE = int(TOWER_Y_RANGE / 2.0)
INITIAL_VELOCITY = 94.0 INITIAL_VELOCITY = 94.0
WHISTLE_SPEED = INITIAL_VELOCITY * 0.55 WHISTLE_SPEED = INITIAL_VELOCITY * 0.55
class DistributedCannonGame(DistributedMinigame): class DistributedCannonGame(DistributedMinigame):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedMinigame') notify = directNotify.newCategory('DistributedCannonGame')
font = ToontownGlobals.getToonFont() font = ToontownGlobals.getToonFont()
LOCAL_CANNON_MOVE_TASK = 'localCannonMoveTask' LOCAL_CANNON_MOVE_TASK = 'localCannonMoveTask'
REWARD_COUNTDOWN_TASK = 'cannonGameRewardCountdown' REWARD_COUNTDOWN_TASK = 'cannonGameRewardCountdown'
@ -58,11 +64,11 @@ class DistributedCannonGame(DistributedMinigame):
def __init__(self, cr): def __init__(self, cr):
DistributedMinigame.__init__(self, cr) DistributedMinigame.__init__(self, cr)
self.gameFSM = ClassicFSM.ClassicFSM('DistributedCannonGame', [State.State('off', self.enterOff, self.exitOff, ['aim']), self.gameFSM = ClassicFSM('DistributedCannonGame', [State('off', self.enterOff, self.exitOff, ['aim']),
State.State('aim', self.enterAim, self.exitAim, ['shoot', 'waitForToonsToLand', 'cleanup']), State('aim', self.enterAim, self.exitAim, ['shoot', 'waitForToonsToLand', 'cleanup']),
State.State('shoot', self.enterShoot, self.exitShoot, ['aim', 'waitForToonsToLand', 'cleanup']), State('shoot', self.enterShoot, self.exitShoot, ['aim', 'waitForToonsToLand', 'cleanup']),
State.State('waitForToonsToLand', self.enterWaitForToonsToLand, self.exitWaitForToonsToLand, ['cleanup']), State('waitForToonsToLand', self.enterWaitForToonsToLand, self.exitWaitForToonsToLand, ['cleanup']),
State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup')
self.addChildGameFSM(self.gameFSM) self.addChildGameFSM(self.gameFSM)
self.cannonLocationDict = {} self.cannonLocationDict = {}
self.cannonPositionDict = {} self.cannonPositionDict = {}
@ -92,12 +98,12 @@ class DistributedCannonGame(DistributedMinigame):
def load(self): def load(self):
self.notify.debug('load') self.notify.debug('load')
DistributedMinigame.load(self) DistributedMinigame.load(self)
self.sky = loader.loadModel('phase_3.5/models/props/TT_sky') self.sky = base.loader.loadModel('phase_3.5/models/props/TT_sky')
self.ground = loader.loadModel('phase_4/models/minigames/toon_cannon_gameground') self.ground = base.loader.loadModel('phase_4/models/minigames/toon_cannon_gameground')
self.tower = loader.loadModel('phase_4/models/minigames/toon_cannon_water_tower') self.tower = base.loader.loadModel('phase_4/models/minigames/toon_cannon_water_tower')
self.cannon = loader.loadModel('phase_4/models/minigames/toon_cannon') self.cannon = base.loader.loadModel('phase_4/models/minigames/toon_cannon')
self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow') self.dropShadow = base.loader.loadModel('phase_3/models/props/drop_shadow')
self.hill = loader.loadModel('phase_4/models/minigames/cannon_hill') self.hill = base.loader.loadModel('phase_4/models/minigames/cannon_hill')
self.sky.setScale(WORLD_SCALE) self.sky.setScale(WORLD_SCALE)
self.ground.setScale(GROUND_SCALE) self.ground.setScale(GROUND_SCALE)
self.cannon.setScale(CANNON_SCALE) self.cannon.setScale(CANNON_SCALE)
@ -105,12 +111,12 @@ class DistributedCannonGame(DistributedMinigame):
self.ground.setColor(0.85, 0.85, 0.85, 1.0) self.ground.setColor(0.85, 0.85, 0.85, 1.0)
self.hill.setScale(1, 1, CANNON_Z / 20.0) self.hill.setScale(1, 1, CANNON_Z / 20.0)
self.dropShadow.setBin('fixed', 0, 1) self.dropShadow.setBin('fixed', 0, 1)
self.splash = Splash.Splash(render) self.splash = Splash(base.render)
self.dustCloud = DustCloud.DustCloud(render) self.dustCloud = DustCloud(base.render)
purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui') purchaseModels = base.loader.loadModel('phase_4/models/gui/purchase_gui')
self.jarImage = purchaseModels.find('**/Jar') self.jarImage = purchaseModels.find('**/Jar')
self.jarImage.reparentTo(hidden) self.jarImage.reparentTo(base.hidden)
self.rewardPanel = DirectLabel(parent=hidden, relief=None, pos=(1.16, 0.0, 0.45), scale=0.65, text='', text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -.13), text_font=ToontownGlobals.getSignFont(), image=self.jarImage) self.rewardPanel = DirectLabel(parent=base.hidden, relief=None, pos=(1.16, 0.0, 0.45), scale=0.65, text='', text_scale=0.2, text_fg=(0.95, 0.95, 0, 1), text_pos=(0, -.13), text_font=ToontownGlobals.getSignFont(), image=self.jarImage)
self.rewardPanelTitle = DirectLabel(parent=self.rewardPanel, relief=None, pos=(0, 0, 0.06), scale=0.08, text=TTLocalizer.CannonGameReward, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1)) self.rewardPanelTitle = DirectLabel(parent=self.rewardPanel, relief=None, pos=(0, 0, 0.06), scale=0.08, text=TTLocalizer.CannonGameReward, text_fg=(0.95, 0.95, 0, 1), text_shadow=(0, 0, 0, 1))
self.music = base.loader.loadMusic('phase_4/audio/bgm/MG_cannon_game.ogg') self.music = base.loader.loadMusic('phase_4/audio/bgm/MG_cannon_game.ogg')
self.sndCannonMove = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_adjust.ogg') self.sndCannonMove = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_adjust.ogg')
@ -122,7 +128,7 @@ class DistributedCannonGame(DistributedMinigame):
self.sndWin = base.loader.loadSfx('phase_4/audio/sfx/MG_win.ogg') self.sndWin = base.loader.loadSfx('phase_4/audio/sfx/MG_win.ogg')
self.sndRewardTick = base.loader.loadSfx('phase_3.5/audio/sfx/tick_counter.ogg') self.sndRewardTick = base.loader.loadSfx('phase_3.5/audio/sfx/tick_counter.ogg')
guiModel = 'phase_4/models/gui/cannon_game_gui' guiModel = 'phase_4/models/gui/cannon_game_gui'
cannonGui = loader.loadModel(guiModel) cannonGui = base.loader.loadModel(guiModel)
self.aimPad = DirectFrame(image=cannonGui.find('**/CannonFire_PAD'), relief=None, pos=(0.7, 0, -0.553333), scale=0.8) self.aimPad = DirectFrame(image=cannonGui.find('**/CannonFire_PAD'), relief=None, pos=(0.7, 0, -0.553333), scale=0.8)
cannonGui.removeNode() cannonGui.removeNode()
self.aimPad.hide() self.aimPad.hide()
@ -141,14 +147,13 @@ class DistributedCannonGame(DistributedMinigame):
bindButton(self.downButton, self.__downPressed, self.__downReleased) bindButton(self.downButton, self.__downPressed, self.__downReleased)
bindButton(self.leftButton, self.__leftPressed, self.__leftReleased) bindButton(self.leftButton, self.__leftPressed, self.__leftReleased)
bindButton(self.rightButton, self.__rightPressed, self.__rightReleased) bindButton(self.rightButton, self.__rightPressed, self.__rightReleased)
self.timer = ToontownTimer.ToontownTimer() self.timer = ToontownTimer()
self.timer.posInTopRightCorner() self.timer.posInTopRightCorner()
self.timer.hide() self.timer.hide()
self.DEBUG_TOWER_RANGE = 0 self.DEBUG_TOWER_RANGE = 0
self.DEBUG_CANNON_FAR_LEFT = 0 self.DEBUG_CANNON_FAR_LEFT = 0
self.DEBUG_TOWER_NEAR = 1 self.DEBUG_TOWER_NEAR = 1
self.DEBUG_TOWER_FAR_LEFT = 1 self.DEBUG_TOWER_FAR_LEFT = 1
return
def unload(self): def unload(self):
self.notify.debug('unload') self.notify.debug('unload')
@ -199,6 +204,7 @@ class DistributedCannonGame(DistributedMinigame):
av.loop('neutral') av.loop('neutral')
av.setPlayRate(1.0, 'run') av.setPlayRate(1.0, 'run')
av.nametag.removeNametag(head.tag) av.nametag.removeNametag(head.tag)
head.delete() head.delete()
del self.toonHeadDict del self.toonHeadDict
@ -227,19 +233,19 @@ class DistributedCannonGame(DistributedMinigame):
DistributedMinigame.onstage(self) DistributedMinigame.onstage(self)
self.__createCannons() self.__createCannons()
for avId in self.avIdList: for avId in self.avIdList:
self.cannonDict[avId][0].reparentTo(render) self.cannonDict[avId][0].reparentTo(base.render)
self.towerPos = self.getTowerPosition() self.towerPos = self.getTowerPosition()
self.tower.setPos(self.towerPos) self.tower.setPos(self.towerPos)
self.tower.reparentTo(render) self.tower.reparentTo(base.render)
self.sky.reparentTo(render) self.sky.reparentTo(base.render)
self.ground.reparentTo(render) self.ground.reparentTo(base.render)
self.hill.setPosHpr(0, CANNON_Y + 2.33, 0, 0, 0, 0) self.hill.setPosHpr(0, CANNON_Y + 2.33, 0, 0, 0, 0)
self.hill.reparentTo(render) self.hill.reparentTo(base.render)
self.splash.reparentTo(render) self.splash.reparentTo(base.render)
self.dustCloud.reparentTo(render) self.dustCloud.reparentTo(base.render)
self.__createToonModels(self.localAvId) self.__createToonModels(self.localAvId)
camera.reparentTo(render) base.camera.reparentTo(base.render)
self.__oldCamFar = base.camLens.getFar() self.__oldCamFar = base.camLens.getFar()
base.camLens.setFar(FAR_PLANE_DIST) base.camLens.setFar(FAR_PLANE_DIST)
self.__startIntro() self.__startIntro()
@ -248,27 +254,28 @@ class DistributedCannonGame(DistributedMinigame):
def offstage(self): def offstage(self):
self.notify.debug('offstage') self.notify.debug('offstage')
self.sky.reparentTo(hidden) self.sky.reparentTo(base.hidden)
self.ground.reparentTo(hidden) self.ground.reparentTo(base.hidden)
self.hill.reparentTo(hidden) self.hill.reparentTo(base.hidden)
self.tower.reparentTo(hidden) self.tower.reparentTo(base.hidden)
for avId in self.avIdList: for avId in self.avIdList:
self.cannonDict[avId][0].reparentTo(hidden) self.cannonDict[avId][0].reparentTo(base.hidden)
if avId in self.dropShadowDict: if avId in self.dropShadowDict:
self.dropShadowDict[avId].reparentTo(hidden) self.dropShadowDict[avId].reparentTo(base.hidden)
av = self.getAvatar(avId) av = self.getAvatar(avId)
if av: if av:
av.dropShadow.show() av.dropShadow.show()
av.resetLOD() av.resetLOD()
self.splash.reparentTo(hidden) self.splash.reparentTo(base.hidden)
self.splash.stop() self.splash.stop()
self.dustCloud.reparentTo(hidden) self.dustCloud.reparentTo(base.hidden)
self.dustCloud.stop() self.dustCloud.stop()
self.__stopIntro() self.__stopIntro()
base.camLens.setFar(self.__oldCamFar) base.camLens.setFar(self.__oldCamFar)
self.timer.reparentTo(hidden) self.timer.reparentTo(base.hidden)
self.rewardPanel.reparentTo(hidden) self.rewardPanel.reparentTo(base.hidden)
DistributedMinigame.offstage(self) DistributedMinigame.offstage(self)
def getTowerPosition(self): def getTowerPosition(self):
@ -282,6 +289,7 @@ class DistributedCannonGame(DistributedMinigame):
y = yMax y = yMax
else: else:
y = self.randomNumGen.randint(yMin, yMax) y = self.randomNumGen.randint(yMin, yMax)
xRange = TOWER_X_RANGE xRange = TOWER_X_RANGE
if self.DEBUG_TOWER_RANGE: if self.DEBUG_TOWER_RANGE:
if self.DEBUG_TOWER_FAR_LEFT: if self.DEBUG_TOWER_FAR_LEFT:
@ -290,6 +298,7 @@ class DistributedCannonGame(DistributedMinigame):
x = xRange x = xRange
else: else:
x = self.randomNumGen.randint(0, xRange) x = self.randomNumGen.randint(0, xRange)
x = x - int(xRange / 2.0) x = x - int(xRange / 2.0)
if base.wantMinigameDifficulty: if base.wantMinigameDifficulty:
diff = self.getDifficulty() diff = self.getDifficulty()
@ -297,6 +306,7 @@ class DistributedCannonGame(DistributedMinigame):
x *= scale x *= scale
yCenter = (yMin + yMax) / 2.0 yCenter = (yMin + yMax) / 2.0
y = (y - yCenter) * scale + yCenter y = (y - yCenter) * scale + yCenter
x = float(x) * (float(y) / float(yRange)) x = float(x) * (float(y) / float(yRange))
y = y - int(yRange / 2.0) y = y - int(yRange / 2.0)
self.notify.debug('getTowerPosition: ' + str(x) + ', ' + str(y)) self.notify.debug('getTowerPosition: ' + str(x) + ', ' + str(y))
@ -304,7 +314,7 @@ class DistributedCannonGame(DistributedMinigame):
def __createCannons(self): def __createCannons(self):
for avId in self.avIdList: for avId in self.avIdList:
cannon = self.cannon.copyTo(hidden) cannon = self.cannon.copyTo(base.hidden)
barrel = cannon.find('**/cannon') barrel = cannon.find('**/cannon')
self.cannonDict[avId] = [cannon, barrel] self.cannonDict[avId] = [cannon, barrel]
@ -317,6 +327,7 @@ class DistributedCannonGame(DistributedMinigame):
self.cannonLocationDict[avId] = Point3(0 * CANNON_X_SPACING - (4 - 1) * CANNON_X_SPACING / 2, CANNON_Y, CANNON_Z) self.cannonLocationDict[avId] = Point3(0 * CANNON_X_SPACING - (4 - 1) * CANNON_X_SPACING / 2, CANNON_Y, CANNON_Z)
else: else:
self.cannonLocationDict[avId] = Point3(3 * CANNON_X_SPACING - (4 - 1) * CANNON_X_SPACING / 2, CANNON_Y, CANNON_Z) self.cannonLocationDict[avId] = Point3(3 * CANNON_X_SPACING - (4 - 1) * CANNON_X_SPACING / 2, CANNON_Y, CANNON_Z)
self.cannonPositionDict[avId] = [0, CannonGameGlobals.CANNON_ANGLE_MIN] self.cannonPositionDict[avId] = [0, CannonGameGlobals.CANNON_ANGLE_MIN]
self.cannonDict[avId][0].setPos(self.cannonLocationDict[avId]) self.cannonDict[avId][0].setPos(self.cannonLocationDict[avId])
self.__updateCannonPosition(avId) self.__updateCannonPosition(avId)
@ -324,9 +335,11 @@ class DistributedCannonGame(DistributedMinigame):
def setGameReady(self): def setGameReady(self):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
self.notify.debug('setGameReady') self.notify.debug('setGameReady')
if DistributedMinigame.setGameReady(self): if DistributedMinigame.setGameReady(self):
return return
for avId in self.avIdList: for avId in self.avIdList:
if avId != self.localAvId: if avId != self.localAvId:
self.__createToonModels(avId) self.__createToonModels(avId)
@ -335,13 +348,13 @@ class DistributedCannonGame(DistributedMinigame):
toon = self.getAvatar(avId) toon = self.getAvatar(avId)
self.toonScaleDict[avId] = toon.getScale() self.toonScaleDict[avId] = toon.getScale()
toon.useLOD(1000) toon.useLOD(1000)
toonParent = render.attachNewNode('toonOriginChange') toonParent = base.render.attachNewNode('toonOriginChange')
toon.reparentTo(toonParent) toon.reparentTo(toonParent)
toon.setPosHpr(0, 0, -(toon.getHeight() / 2.0), 0, 0, 0) toon.setPosHpr(0, 0, -(toon.getHeight() / 2.0), 0, 0, 0)
self.toonModelDict[avId] = toonParent self.toonModelDict[avId] = toonParent
head = ToonHead.ToonHead() head = ToonHead()
head.setupHead(self.getAvatar(avId).style) head.setupHead(self.getAvatar(avId).style)
head.reparentTo(hidden) head.reparentTo(base.hidden)
self.toonHeadDict[avId] = head self.toonHeadDict[avId] = head
toon = self.getAvatar(avId) toon = self.getAvatar(avId)
tag = NametagFloat3d() tag = NametagFloat3d()
@ -354,11 +367,12 @@ class DistributedCannonGame(DistributedMinigame):
head.tag = tag head.tag = tag
self.__loadToonInCannon(avId) self.__loadToonInCannon(avId)
self.getAvatar(avId).dropShadow.hide() self.getAvatar(avId).dropShadow.hide()
self.dropShadowDict[avId] = self.dropShadow.copyTo(hidden) self.dropShadowDict[avId] = self.dropShadow.copyTo(base.hidden)
def setGameStart(self, timestamp): def setGameStart(self, timestamp):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
self.notify.debug('setGameStart') self.notify.debug('setGameStart')
DistributedMinigame.setGameStart(self, timestamp) DistributedMinigame.setGameStart(self, timestamp)
self.__stopIntro() self.__stopIntro()
@ -366,13 +380,13 @@ class DistributedCannonGame(DistributedMinigame):
if not base.config.GetBool('endless-cannon-game', 0): if not base.config.GetBool('endless-cannon-game', 0):
self.timer.show() self.timer.show()
self.timer.countdown(CannonGameGlobals.GameTime, self.__gameTimerExpired) self.timer.countdown(CannonGameGlobals.GameTime, self.__gameTimerExpired)
self.rewardPanel.reparentTo(aspect2d)
self.rewardPanel.reparentTo(base.aspect2d)
self.scoreMult = MinigameGlobals.getScoreMult(self.cr.playGame.hood.id) self.scoreMult = MinigameGlobals.getScoreMult(self.cr.playGame.hood.id)
self.__startRewardCountdown() self.__startRewardCountdown()
self.airborneToons = 0 self.airborneToons = 0
self.clockStopTime = None self.clockStopTime = None
self.gameFSM.request('aim') self.gameFSM.request('aim')
return
def __gameTimerExpired(self): def __gameTimerExpired(self):
self.notify.debug('game timer expired') self.notify.debug('game timer expired')
@ -384,8 +398,10 @@ class DistributedCannonGame(DistributedMinigame):
def updateCannonPosition(self, avId, zRot, angle): def updateCannonPosition(self, avId, zRot, angle):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
if not self.__playing(): if not self.__playing():
return return
if avId != self.localAvId: if avId != self.localAvId:
self.cannonPositionDict[avId] = [zRot, angle] self.cannonPositionDict[avId] = [zRot, angle]
self.__updateCannonPosition(avId) self.__updateCannonPosition(avId)
@ -393,8 +409,10 @@ class DistributedCannonGame(DistributedMinigame):
def setCannonWillFire(self, avId, fireTime, zRot, angle): def setCannonWillFire(self, avId, fireTime, zRot, angle):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
if not self.__playing(): if not self.__playing():
return return
self.notify.debug('setCannonWillFire: ' + str(avId) + ': zRot=' + str(zRot) + ', angle=' + str(angle) + ', time=' + str(fireTime)) self.notify.debug('setCannonWillFire: ' + str(avId) + ': zRot=' + str(zRot) + ', angle=' + str(angle) + ', time=' + str(fireTime))
self.cannonPositionDict[avId][0] = zRot self.cannonPositionDict[avId][0] = zRot
self.cannonPositionDict[avId][1] = angle self.cannonPositionDict[avId][1] = angle
@ -407,6 +425,7 @@ class DistributedCannonGame(DistributedMinigame):
fireTask = Task.sequence(Task.pause(timeToWait), task) fireTask = Task.sequence(Task.pause(timeToWait), task)
else: else:
fireTask = task fireTask = task
fireTask = task fireTask = task
taskMgr.add(fireTask, 'fireCannon' + str(avId)) taskMgr.add(fireTask, 'fireCannon' + str(avId))
self.airborneToons += 1 self.airborneToons += 1
@ -414,10 +433,10 @@ class DistributedCannonGame(DistributedMinigame):
def announceToonWillLandInWater(self, avId, landTime): def announceToonWillLandInWater(self, avId, landTime):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
self.notify.debug('announceToonWillLandInWater: ' + str(avId) + ': time=' + str(landTime)) self.notify.debug('announceToonWillLandInWater: ' + str(avId) + ': time=' + str(landTime))
if self.clockStopTime == None: if self.clockStopTime == None:
self.clockStopTime = landTime self.clockStopTime = landTime
return
def enterOff(self): def enterOff(self):
self.notify.debug('enterOff') self.notify.debug('enterOff')
@ -444,6 +463,7 @@ class DistributedCannonGame(DistributedMinigame):
def __somebodyWon(self, avId): def __somebodyWon(self, avId):
if avId == self.localAvId: if avId == self.localAvId:
base.playSfx(self.sndWin) base.playSfx(self.sndWin)
self.__killRewardCountdown() self.__killRewardCountdown()
self.timer.stop() self.timer.stop()
self.gameFSM.request('waitForToonsToLand') self.gameFSM.request('waitForToonsToLand')
@ -463,6 +483,7 @@ class DistributedCannonGame(DistributedMinigame):
if hasattr(self, 'jarIval'): if hasattr(self, 'jarIval'):
self.jarIval.finish() self.jarIval.finish()
del self.jarIval del self.jarIval
for avId in self.avIdList: for avId in self.avIdList:
taskMgr.remove('fireCannon' + str(avId)) taskMgr.remove('fireCannon' + str(avId))
taskMgr.remove('flyingToon' + str(avId)) taskMgr.remove('flyingToon' + str(avId))
@ -607,27 +628,34 @@ class DistributedCannonGame(DistributedMinigame):
rotVel = 0 rotVel = 0
if self.leftPressed: if self.leftPressed:
rotVel += CannonGameGlobals.CANNON_ROTATION_VEL rotVel += CannonGameGlobals.CANNON_ROTATION_VEL
if self.rightPressed: if self.rightPressed:
rotVel -= CannonGameGlobals.CANNON_ROTATION_VEL rotVel -= CannonGameGlobals.CANNON_ROTATION_VEL
pos[0] += rotVel * globalClock.getDt()
pos[0] += rotVel * base.clock.getDt()
if pos[0] < CannonGameGlobals.CANNON_ROTATION_MIN: if pos[0] < CannonGameGlobals.CANNON_ROTATION_MIN:
pos[0] = CannonGameGlobals.CANNON_ROTATION_MIN pos[0] = CannonGameGlobals.CANNON_ROTATION_MIN
elif pos[0] > CannonGameGlobals.CANNON_ROTATION_MAX: elif pos[0] > CannonGameGlobals.CANNON_ROTATION_MAX:
pos[0] = CannonGameGlobals.CANNON_ROTATION_MAX pos[0] = CannonGameGlobals.CANNON_ROTATION_MAX
angVel = 0 angVel = 0
if self.upPressed: if self.upPressed:
angVel += CannonGameGlobals.CANNON_ANGLE_VEL angVel += CannonGameGlobals.CANNON_ANGLE_VEL
if self.downPressed: if self.downPressed:
angVel -= CannonGameGlobals.CANNON_ANGLE_VEL angVel -= CannonGameGlobals.CANNON_ANGLE_VEL
pos[1] += angVel * globalClock.getDt()
pos[1] += angVel * base.clock.getDt()
if pos[1] < CannonGameGlobals.CANNON_ANGLE_MIN: if pos[1] < CannonGameGlobals.CANNON_ANGLE_MIN:
pos[1] = CannonGameGlobals.CANNON_ANGLE_MIN pos[1] = CannonGameGlobals.CANNON_ANGLE_MIN
elif pos[1] > CannonGameGlobals.CANNON_ANGLE_MAX: elif pos[1] > CannonGameGlobals.CANNON_ANGLE_MAX:
pos[1] = CannonGameGlobals.CANNON_ANGLE_MAX pos[1] = CannonGameGlobals.CANNON_ANGLE_MAX
if oldRot != pos[0] or oldAng != pos[1]: if oldRot != pos[0] or oldAng != pos[1]:
if self.cannonMoving == 0: if self.cannonMoving == 0:
self.cannonMoving = 1 self.cannonMoving = 1
base.playSfx(self.sndCannonMove, looping=1) base.playSfx(self.sndCannonMove, looping=1)
self.__updateCannonPosition(self.localAvId) self.__updateCannonPosition(self.localAvId)
if task.time - task.lastPositionBroadcastTime > CANNON_MOVE_UPDATE_FREQ: if task.time - task.lastPositionBroadcastTime > CANNON_MOVE_UPDATE_FREQ:
task.lastPositionBroadcastTime = task.time task.lastPositionBroadcastTime = task.time
@ -636,7 +664,8 @@ class DistributedCannonGame(DistributedMinigame):
self.cannonMoving = 0 self.cannonMoving = 0
self.sndCannonMove.stop() self.sndCannonMove.stop()
self.__broadcastLocalCannonPosition() self.__broadcastLocalCannonPosition()
return Task.cont
return task.cont
def __broadcastLocalCannonPosition(self): def __broadcastLocalCannonPosition(self):
self.sendUpdate('setCannonPosition', [self.cannonPositionDict[self.localAvId][0], self.cannonPositionDict[self.localAvId][1]]) self.sendUpdate('setCannonPosition', [self.cannonPositionDict[self.localAvId][0], self.cannonPositionDict[self.localAvId][1]])
@ -649,8 +678,8 @@ class DistributedCannonGame(DistributedMinigame):
return Point3(self.cannonLocationDict[self.localAvId][0], CANNON_Y - 25.0, CANNON_Z + 7) return Point3(self.cannonLocationDict[self.localAvId][0], CANNON_Y - 25.0, CANNON_Z + 7)
def __putCameraBehindCannon(self): def __putCameraBehindCannon(self):
camera.setPos(self.__getCameraPositionBehindCannon()) base.camera.setPos(self.__getCameraPositionBehindCannon())
camera.setHpr(0, 0, 0) base.camera.setHpr(0, 0, 0)
def __loadToonInCannon(self, avId): def __loadToonInCannon(self, avId):
self.toonModelDict[avId].detachNode() self.toonModelDict[avId].detachNode()
@ -660,7 +689,7 @@ class DistributedCannonGame(DistributedMinigame):
head.reparentTo(self.cannonDict[avId][1]) head.reparentTo(self.cannonDict[avId][1])
head.setPosHpr(0, 6, 0, 0, -45, 0) head.setPosHpr(0, 6, 0, 0, -45, 0)
sc = self.toonScaleDict[avId] sc = self.toonScaleDict[avId]
head.setScale(render, sc[0], sc[1], sc[2]) head.setScale(base.render, sc[0], sc[1], sc[2])
def __toRadians(self, angle): def __toRadians(self, angle):
return angle * 2.0 * math.pi / 360.0 return angle * 2.0 * math.pi / 360.0
@ -670,10 +699,10 @@ class DistributedCannonGame(DistributedMinigame):
def __calcFlightResults(self, avId, launchTime): def __calcFlightResults(self, avId, launchTime):
head = self.toonHeadDict[avId] head = self.toonHeadDict[avId]
startPos = head.getPos(render) startPos = head.getPos(base.render)
startHpr = head.getHpr(render) startHpr = head.getHpr(base.render)
hpr = self.cannonDict[avId][1].getHpr(render) hpr = self.cannonDict[avId][1].getHpr(base.render)
towerPos = self.tower.getPos(render) towerPos = self.tower.getPos(base.render)
rotation = self.__toRadians(hpr[0]) rotation = self.__toRadians(hpr[0])
angle = self.__toRadians(hpr[1]) angle = self.__toRadians(hpr[1])
horizVel = INITIAL_VELOCITY * math.cos(angle) horizVel = INITIAL_VELOCITY * math.cos(angle)
@ -681,7 +710,7 @@ class DistributedCannonGame(DistributedMinigame):
yVel = horizVel * math.cos(rotation) yVel = horizVel * math.cos(rotation)
zVel = INITIAL_VELOCITY * math.sin(angle) zVel = INITIAL_VELOCITY * math.sin(angle)
startVel = Vec3(xVel, yVel, zVel) startVel = Vec3(xVel, yVel, zVel)
trajectory = Trajectory.Trajectory(launchTime, startPos, startVel) trajectory = Trajectory(launchTime, startPos, startVel)
towerList = [towerPos + Point3(0, 0, BUCKET_HEIGHT), TOWER_RADIUS, TOWER_HEIGHT - BUCKET_HEIGHT] towerList = [towerPos + Point3(0, 0, BUCKET_HEIGHT), TOWER_RADIUS, TOWER_HEIGHT - BUCKET_HEIGHT]
self.notify.debug('calcFlightResults(%s): rotation(%s), angle(%s), horizVel(%s), xVel(%s), yVel(%s), zVel(%s), startVel(%s), trajectory(%s), towerList(%s)' % (avId, self.notify.debug('calcFlightResults(%s): rotation(%s), angle(%s), horizVel(%s), xVel(%s), yVel(%s), zVel(%s), startVel(%s), trajectory(%s), towerList(%s)' % (avId,
rotation, rotation,
@ -701,7 +730,6 @@ class DistributedCannonGame(DistributedMinigame):
avId = task.avId avId = task.avId
self.notify.debug('FIRING CANNON FOR AVATAR ' + str(avId)) self.notify.debug('FIRING CANNON FOR AVATAR ' + str(avId))
startPos, startHpr, startVel, trajectory, timeOfImpact, hitWhat = self.__calcFlightResults(avId, launchTime) startPos, startHpr, startVel, trajectory, timeOfImpact, hitWhat = self.__calcFlightResults(avId, launchTime)
self.notify.debug('start position: ' + str(startPos)) self.notify.debug('start position: ' + str(startPos))
self.notify.debug('start velocity: ' + str(startVel)) self.notify.debug('start velocity: ' + str(startVel))
self.notify.debug('time of launch: ' + str(launchTime)) self.notify.debug('time of launch: ' + str(launchTime))
@ -713,12 +741,13 @@ class DistributedCannonGame(DistributedMinigame):
self.notify.debug('toon will hit the tower') self.notify.debug('toon will hit the tower')
else: else:
self.notify.debug('toon will hit the ground') self.notify.debug('toon will hit the ground')
head = self.toonHeadDict[avId] head = self.toonHeadDict[avId]
head.stopBlink() head.stopBlink()
head.stopLookAroundNow() head.stopLookAroundNow()
head.reparentTo(hidden) head.reparentTo(base.hidden)
av = self.toonModelDict[avId] av = self.toonModelDict[avId]
av.reparentTo(render) av.reparentTo(base.render)
av.setPos(startPos) av.setPos(startPos)
av.setHpr(startHpr) av.setHpr(startHpr)
avatar = self.getAvatar(avId) avatar = self.getAvatar(avId)
@ -737,7 +766,7 @@ class DistributedCannonGame(DistributedMinigame):
info['hRot'] = self.cannonPositionDict[avId][0] info['hRot'] = self.cannonPositionDict[avId][0]
info['haveWhistled'] = 0 info['haveWhistled'] = 0
info['maxCamPullback'] = CAMERA_PULLBACK_MIN info['maxCamPullback'] = CAMERA_PULLBACK_MIN
info['timeEnterTowerXY'], info['timeExitTowerXY'] = trajectory.calcEnterAndLeaveCylinderXY(self.tower.getPos(render), TOWER_RADIUS) info['timeEnterTowerXY'], info['timeExitTowerXY'] = trajectory.calcEnterAndLeaveCylinderXY(self.tower.getPos(base.render), TOWER_RADIUS)
shootTask.info = info shootTask.info = info
flyTask.info = info flyTask.info = info
seqDoneTask.info = info seqDoneTask.info = info
@ -746,7 +775,8 @@ class DistributedCannonGame(DistributedMinigame):
if avId == self.localAvId: if avId == self.localAvId:
if info['hitWhat'] == self.HIT_WATER: if info['hitWhat'] == self.HIT_WATER:
self.sendUpdate('setToonWillLandInWater', [info['timeOfImpact']]) self.sendUpdate('setToonWillLandInWater', [info['timeOfImpact']])
return Task.done
return task.done
def __calcToonImpact(self, trajectory, waterTower): def __calcToonImpact(self, trajectory, waterTower):
self.notify.debug('trajectory: %s' % trajectory) self.notify.debug('trajectory: %s' % trajectory)
@ -757,10 +787,12 @@ class DistributedCannonGame(DistributedMinigame):
self.notify.debug('t_waterImpact: %s' % t_waterImpact) self.notify.debug('t_waterImpact: %s' % t_waterImpact)
if t_waterImpact > 0: if t_waterImpact > 0:
return (t_waterImpact, self.HIT_WATER) return (t_waterImpact, self.HIT_WATER)
t_towerImpact = trajectory.checkCollisionWithCylinderSides(waterTower[0], waterTower[1], waterTower[2]) t_towerImpact = trajectory.checkCollisionWithCylinderSides(waterTower[0], waterTower[1], waterTower[2])
self.notify.debug('t_towerImpact: %s' % t_towerImpact) self.notify.debug('t_towerImpact: %s' % t_towerImpact)
if t_towerImpact > 0: if t_towerImpact > 0:
return (t_towerImpact, self.HIT_TOWER) return (t_towerImpact, self.HIT_TOWER)
t_groundImpact = trajectory.checkCollisionWithGround() t_groundImpact = trajectory.checkCollisionWithGround()
self.notify.debug('t_groundImpact: %s' % t_groundImpact) self.notify.debug('t_groundImpact: %s' % t_groundImpact)
if t_groundImpact >= trajectory.getStartTime(): if t_groundImpact >= trajectory.getStartTime():
@ -771,8 +803,8 @@ class DistributedCannonGame(DistributedMinigame):
def __shootTask(self, task): def __shootTask(self, task):
base.playSfx(self.sndCannonFire) base.playSfx(self.sndCannonFire)
self.dropShadowDict[task.info['avId']].reparentTo(render) self.dropShadowDict[task.info['avId']].reparentTo(base.render)
return Task.done return task.done
def __flyTask(self, task): def __flyTask(self, task):
curTime = task.time + task.info['launchTime'] curTime = task.time + task.info['launchTime']
@ -780,10 +812,11 @@ class DistributedCannonGame(DistributedMinigame):
pos = task.info['trajectory'].getPos(t) pos = task.info['trajectory'].getPos(t)
task.info['toon'].setPos(pos) task.info['toon'].setPos(pos)
shadowPos = Point3(pos) shadowPos = Point3(pos)
if t >= task.info['timeEnterTowerXY'] and t <= task.info['timeExitTowerXY'] and pos[2] >= self.tower.getPos(render)[2] + TOWER_HEIGHT: if t >= task.info['timeEnterTowerXY'] and t <= task.info['timeExitTowerXY'] and pos[2] >= self.tower.getPos(base.render)[2] + TOWER_HEIGHT:
shadowPos.setZ(self.tower.getPos(render)[2] + TOWER_HEIGHT + SHADOW_Z_OFFSET) shadowPos.setZ(self.tower.getPos(base.render)[2] + TOWER_HEIGHT + SHADOW_Z_OFFSET)
else: else:
shadowPos.setZ(SHADOW_Z_OFFSET) shadowPos.setZ(SHADOW_Z_OFFSET)
self.dropShadowDict[task.info['avId']].setPos(shadowPos) self.dropShadowDict[task.info['avId']].setPos(shadowPos)
vel = task.info['trajectory'].getVel(t) vel = task.info['trajectory'].getVel(t)
run = math.sqrt(vel[0] * vel[0] + vel[1] * vel[1]) run = math.sqrt(vel[0] * vel[0] + vel[1] * vel[1])
@ -791,7 +824,7 @@ class DistributedCannonGame(DistributedMinigame):
theta = self.__toDegrees(math.atan(rise / run)) theta = self.__toDegrees(math.atan(rise / run))
task.info['toon'].setHpr(task.info['hRot'], -90 + theta, 0) task.info['toon'].setHpr(task.info['hRot'], -90 + theta, 0)
if task.info['avId'] == self.localAvId: if task.info['avId'] == self.localAvId:
lookAt = self.tower.getPos(render) lookAt = self.tower.getPos(base.render)
lookAt.setZ(lookAt.getZ() - TOWER_HEIGHT / 2.0) lookAt.setZ(lookAt.getZ() - TOWER_HEIGHT / 2.0)
towerPos = Point3(self.towerPos) towerPos = Point3(self.towerPos)
towerPos.setZ(TOWER_HEIGHT) towerPos.setZ(TOWER_HEIGHT)
@ -804,26 +837,31 @@ class DistributedCannonGame(DistributedMinigame):
perp.normalize() perp.normalize()
if ttVec.dot(perp) > 0.0: if ttVec.dot(perp) > 0.0:
perp = Vec3(-perp[0], -perp[1], -perp[2]) perp = Vec3(-perp[0], -perp[1], -perp[2])
a = 1.0 - toonTowerDist / TOON_TOWER_THRESHOLD a = 1.0 - toonTowerDist / TOON_TOWER_THRESHOLD
a_2 = a * a a_2 = a * a
multiplier = -2.0 * a_2 * a + 3 * a_2 multiplier = -2.0 * a_2 * a + 3 * a_2
lookAt = lookAt + perp * (multiplier * MAX_LOOKAT_OFFSET) lookAt = lookAt + perp * (multiplier * MAX_LOOKAT_OFFSET)
foo = Vec3(pos - lookAt) foo = Vec3(pos - lookAt)
foo.normalize() foo.normalize()
task.info['maxCamPullback'] = max(task.info['maxCamPullback'], CAMERA_PULLBACK_MIN + multiplier * (CAMERA_PULLBACK_MAX - CAMERA_PULLBACK_MIN)) task.info['maxCamPullback'] = max(task.info['maxCamPullback'], CAMERA_PULLBACK_MIN + multiplier * (CAMERA_PULLBACK_MAX - CAMERA_PULLBACK_MIN))
foo = foo * task.info['maxCamPullback'] foo = foo * task.info['maxCamPullback']
camPos = pos + Point3(foo) camPos = pos + Point3(foo)
camera.setPos(camPos) base.camera.setPos(camPos)
camera.lookAt(pos) base.camera.lookAt(pos)
if task.info['haveWhistled'] == 0: if task.info['haveWhistled'] == 0:
if -vel[2] > WHISTLE_SPEED: if -vel[2] > WHISTLE_SPEED:
if t < task.info['timeOfImpact'] - 0.5: if t < task.info['timeOfImpact'] - 0.5:
task.info['haveWhistled'] = 1 task.info['haveWhistled'] = 1
base.playSfx(self.sndWhizz) base.playSfx(self.sndWhizz)
if t == task.info['timeOfImpact']: if t == task.info['timeOfImpact']:
if task.info['haveWhistled']: if task.info['haveWhistled']:
self.sndWhizz.stop() self.sndWhizz.stop()
self.dropShadowDict[task.info['avId']].reparentTo(hidden)
self.dropShadowDict[task.info['avId']].reparentTo(base.hidden)
avatar = self.getAvatar(task.info['avId']) avatar = self.getAvatar(task.info['avId'])
if task.info['hitWhat'] == self.HIT_WATER: if task.info['hitWhat'] == self.HIT_WATER:
avatar.loop('neutral') avatar.loop('neutral')
@ -853,15 +891,17 @@ class DistributedCannonGame(DistributedMinigame):
avatar.pose('slip-forward', 25) avatar.pose('slip-forward', 25)
base.playSfx(self.sndHitTower) base.playSfx(self.sndHitTower)
elif task.info['hitWhat'] == self.HIT_GROUND: elif task.info['hitWhat'] == self.HIT_GROUND:
task.info['toon'].setP(render, -150.0) task.info['toon'].setP(base.render, -150.0)
self.dustCloud.setPos(task.info['toon'], 0, 0, -2.5) self.dustCloud.setPos(task.info['toon'], 0, 0, -2.5)
self.dustCloud.setScale(0.35) self.dustCloud.setScale(0.35)
self.dustCloud.play() self.dustCloud.play()
base.playSfx(self.sndHitGround) base.playSfx(self.sndHitGround)
avatar.setPlayRate(2.0, 'run') avatar.setPlayRate(2.0, 'run')
avatar.loop('run') avatar.loop('run')
return Task.done
return Task.cont return task.done
return task.cont
def __flySequenceDoneTask(self, task): def __flySequenceDoneTask(self, task):
self.airborneToons -= 1 self.airborneToons -= 1
@ -872,7 +912,8 @@ class DistributedCannonGame(DistributedMinigame):
self.__loadToonInCannon(task.info['avId']) self.__loadToonInCannon(task.info['avId'])
if task.info['avId'] == self.localAvId: if task.info['avId'] == self.localAvId:
self.gameFSM.request('aim') self.gameFSM.request('aim')
return Task.done
return task.done
def __startRewardCountdown(self): def __startRewardCountdown(self):
taskMgr.remove(self.REWARD_COUNTDOWN_TASK) taskMgr.remove(self.REWARD_COUNTDOWN_TASK)
@ -883,24 +924,29 @@ class DistributedCannonGame(DistributedMinigame):
def __updateRewardCountdown(self, task): def __updateRewardCountdown(self, task):
if not hasattr(self, 'rewardPanel'): if not hasattr(self, 'rewardPanel'):
return Task.cont return task.cont
curTime = self.getCurrentGameTime() curTime = self.getCurrentGameTime()
if self.clockStopTime is not None: if self.clockStopTime is not None:
if self.clockStopTime < curTime: if self.clockStopTime < curTime:
self.__killRewardCountdown() self.__killRewardCountdown()
curTime = self.clockStopTime curTime = self.clockStopTime
score = int(self.scoreMult * CannonGameGlobals.calcScore(curTime) + 0.5) score = int(self.scoreMult * CannonGameGlobals.calcScore(curTime) + 0.5)
if not hasattr(task, 'curScore'): if not hasattr(task, 'curScore'):
task.curScore = score task.curScore = score
self.rewardPanel['text'] = str(score) self.rewardPanel['text'] = str(score)
if task.curScore != score: if task.curScore != score:
if hasattr(self, 'jarIval'): if hasattr(self, 'jarIval'):
self.jarIval.finish() self.jarIval.finish()
s = self.rewardPanel.getScale() s = self.rewardPanel.getScale()
self.jarIval = Parallel(Sequence(self.rewardPanel.scaleInterval(0.15, s * 3.0 / 4.0, blendType='easeOut'), self.rewardPanel.scaleInterval(0.15, s, blendType='easeIn')), SoundInterval(self.sndRewardTick), name='cannonGameRewardJarThrob') self.jarIval = Parallel(Sequence(self.rewardPanel.scaleInterval(0.15, s * 3.0 / 4.0, blendType='easeOut'), self.rewardPanel.scaleInterval(0.15, s, blendType='easeIn')), SoundInterval(self.sndRewardTick), name='cannonGameRewardJarThrob')
self.jarIval.start() self.jarIval.start()
task.curScore = score task.curScore = score
return Task.cont return task.cont
def __startIntro(self): def __startIntro(self):
self.T_WATER = 1 self.T_WATER = 1
@ -926,18 +972,19 @@ class DistributedCannonGame(DistributedMinigame):
if self.introCameraSeq: if self.introCameraSeq:
self.introCameraSeq.finish() self.introCameraSeq.finish()
self.introCameraSeq = None self.introCameraSeq = None
camera.wrtReparentTo(render)
base.camera.wrtReparentTo(base.render)
def __spawnCameraLookAtLerp(self, targetPos, targetLookAt, duration): def __spawnCameraLookAtLerp(self, targetPos, targetLookAt, duration):
oldPos = camera.getPos() oldPos = base.camera.getPos()
oldHpr = camera.getHpr() oldHpr = base.camera.getHpr()
camera.setPos(targetPos) base.camera.setPos(targetPos)
camera.lookAt(targetLookAt) base.camera.lookAt(targetLookAt)
targetQuat = Quat() targetQuat = Quat()
targetQuat.setHpr(camera.getHpr()) targetQuat.setHpr(base.camera.getHpr())
camera.setPos(oldPos) base.camera.setPos(oldPos)
camera.setHpr(oldHpr) base.camera.setHpr(oldHpr)
self.introCameraSeq = camera.posQuatInterval(duration, Point3(targetPos), targetQuat, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP) self.introCameraSeq = base.camera.posQuatInterval(duration, Point3(targetPos), targetQuat, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP)
self.introCameraSeq.start() self.introCameraSeq.start()
def __taskLookInWater(self, task): def __taskLookInWater(self, task):
@ -949,40 +996,40 @@ class DistributedCannonGame(DistributedMinigame):
vecAwayFromCannons.normalize() vecAwayFromCannons.normalize()
camLoc = Point3(vecAwayFromCannons * 20) + Point3(0, 0, 20) camLoc = Point3(vecAwayFromCannons * 20) + Point3(0, 0, 20)
camLoc = camLoc + task.data['towerWaterCenter'] camLoc = camLoc + task.data['towerWaterCenter']
camera.setPos(camLoc) base.camera.setPos(camLoc)
camera.lookAt(task.data['towerWaterCenter']) base.camera.lookAt(task.data['towerWaterCenter'])
task.data['vecAwayFromCannons'] = vecAwayFromCannons task.data['vecAwayFromCannons'] = vecAwayFromCannons
return Task.done return task.done
def __taskPullBackFromWater(self, task): def __taskPullBackFromWater(self, task):
camLoc = Point3(task.data['vecAwayFromCannons'] * 40) + Point3(0, 0, 20) camLoc = Point3(task.data['vecAwayFromCannons'] * 40) + Point3(0, 0, 20)
camLoc = camLoc + task.data['towerWaterCenter'] camLoc = camLoc + task.data['towerWaterCenter']
lookAt = task.data['cannonCenter'] lookAt = task.data['cannonCenter']
self.__spawnCameraLookAtLerp(camLoc, lookAt, self.T_WATER2LONGVIEW) self.__spawnCameraLookAtLerp(camLoc, lookAt, self.T_WATER2LONGVIEW)
return Task.done return task.done
def __flyUpToToon(self, task): def __flyUpToToon(self, task):
headPos = self.toonHeadDict[self.localAvId].getPos(render) headPos = self.toonHeadDict[self.localAvId].getPos(base.render)
camLoc = headPos + Point3(0, 5, 0) camLoc = headPos + Point3(0, 5, 0)
lookAt = Point3(headPos) lookAt = Point3(headPos)
self.__spawnCameraLookAtLerp(camLoc, lookAt, self.T_LONGVIEW2TOONHEAD) self.__spawnCameraLookAtLerp(camLoc, lookAt, self.T_LONGVIEW2TOONHEAD)
return Task.done return task.done
def __flyToBackOfCannon(self, task): def __flyToBackOfCannon(self, task):
lerpNode = hidden.attachNewNode('CannonGameCameraLerpNode') lerpNode = base.hidden.attachNewNode('CannonGameCameraLerpNode')
lerpNode.reparentTo(render) lerpNode.reparentTo(base.render)
lerpNode.setPos(self.cannonLocationDict[self.localAvId] + Point3(0, 1, 0)) lerpNode.setPos(self.cannonLocationDict[self.localAvId] + Point3(0, 1, 0))
relCamPos = camera.getPos(lerpNode) relCamPos = base.camera.getPos(lerpNode)
relCamHpr = camera.getHpr(lerpNode) relCamHpr = base.camera.getHpr(lerpNode)
startRotation = lerpNode.getHpr() startRotation = lerpNode.getHpr()
endRotation = Point3(-180, 0, 0) endRotation = Point3(-180, 0, 0)
lerpNode.setHpr(endRotation) lerpNode.setHpr(endRotation)
camera.setPos(self.__getCameraPositionBehindCannon()) base.camera.setPos(self.__getCameraPositionBehindCannon())
endPos = camera.getPos(lerpNode) endPos = base.camera.getPos(lerpNode)
lerpNode.setHpr(startRotation) lerpNode.setHpr(startRotation)
camera.reparentTo(lerpNode) base.camera.reparentTo(lerpNode)
camera.setPos(relCamPos) base.camera.setPos(relCamPos)
camera.setHpr(relCamHpr) base.camera.setHpr(relCamHpr)
self.introCameraSeq = Parallel(lerpNode.hprInterval(self.T_TOONHEAD2CANNONBACK, endRotation, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP), camera.posInterval(self.T_TOONHEAD2CANNONBACK, endPos, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP)) self.introCameraSeq = Parallel(lerpNode.hprInterval(self.T_TOONHEAD2CANNONBACK, endRotation, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP), base.camera.posInterval(self.T_TOONHEAD2CANNONBACK, endPos, blendType='easeInOut', name=self.INTRO_TASK_NAME_CAMERA_LERP))
self.introCameraSeq.start() self.introCameraSeq.start()
return Task.done return task.done

View file

@ -1,22 +1,36 @@
from panda3d.core import * from panda3d.core import Point3, VBase4, Vec3
from toontown.toonbase.ToonBaseGlobal import * from panda3d.otp import CFSpeech, NametagGlobals
from direct.interval.IntervalGlobal import *
from .DistributedMinigame import * from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.gui.DirectGui import * from direct.fsm.ClassicFSM import ClassicFSM
from panda3d.core import * from direct.fsm.State import State
from direct.fsm import ClassicFSM, State from direct.gui.DirectGui import DirectLabel
from direct.fsm import State from direct.interval.IntervalGlobal import (
from toontown.toonbase import ToontownTimer ActorInterval,
from . import PatternGameGlobals Func,
from toontown.toon import ToonHead LerpColorInterval,
from toontown.char import CharDNA LerpHprInterval,
from toontown.char import Char LerpPosInterval,
from . import ArrowKeys Parallel,
import random Sequence,
Wait
)
from toontown.char.Char import Char
from toontown.char.CharDNA import CharDNA
from toontown.minigame import PatternGameGlobals
from toontown.minigame.ArrowKeys import ArrowKeys
from toontown.minigame.DistributedMinigame import DistributedMinigame
from toontown.toonbase import ToontownGlobals from toontown.toonbase import ToontownGlobals
from toontown.toonbase import TTLocalizer from toontown.toonbase import TTLocalizer
from toontown.toonbase.ToonBaseGlobal import base
from toontown.toonbase.ToontownTimer import ToontownTimer
from random import choice
class DistributedPatternGame(DistributedMinigame): class DistributedPatternGame(DistributedMinigame):
notify = directNotify.newCategory('DistributedPatternGame')
phase4snd = 'phase_4/audio/sfx/' phase4snd = 'phase_4/audio/sfx/'
ButtonSoundNames = (phase4snd + 'm_match_trumpet.ogg', ButtonSoundNames = (phase4snd + 'm_match_trumpet.ogg',
phase4snd + 'm_match_guitar.ogg', phase4snd + 'm_match_guitar.ogg',
@ -46,14 +60,14 @@ class DistributedPatternGame(DistributedMinigame):
def __init__(self, cr): def __init__(self, cr):
DistributedMinigame.__init__(self, cr) DistributedMinigame.__init__(self, cr)
self.gameFSM = ClassicFSM.ClassicFSM('DistributedPatternGame', [State.State('off', self.enterOff, self.exitOff, ['waitForServerPattern']), self.gameFSM = ClassicFSM('DistributedPatternGame', [State('off', self.enterOff, self.exitOff, ['waitForServerPattern']),
State.State('waitForServerPattern', self.enterWaitForServerPattern, self.exitWaitForServerPattern, ['showServerPattern', 'cleanup']), State('waitForServerPattern', self.enterWaitForServerPattern, self.exitWaitForServerPattern, ['showServerPattern', 'cleanup']),
State.State('showServerPattern', self.enterShowServerPattern, self.exitShowServerPattern, ['getUserInput', 'playBackPatterns', 'cleanup']), State('showServerPattern', self.enterShowServerPattern, self.exitShowServerPattern, ['getUserInput', 'playBackPatterns', 'cleanup']),
State.State('getUserInput', self.enterGetUserInput, self.exitGetUserInput, ['waitForPlayerPatterns', 'playBackPatterns', 'cleanup']), State('getUserInput', self.enterGetUserInput, self.exitGetUserInput, ['waitForPlayerPatterns', 'playBackPatterns', 'cleanup']),
State.State('waitForPlayerPatterns', self.enterWaitForPlayerPatterns, self.exitWaitForPlayerPatterns, ['playBackPatterns', 'cleanup', 'checkGameOver']), State('waitForPlayerPatterns', self.enterWaitForPlayerPatterns, self.exitWaitForPlayerPatterns, ['playBackPatterns', 'cleanup', 'checkGameOver']),
State.State('playBackPatterns', self.enterPlayBackPatterns, self.exitPlayBackPatterns, ['checkGameOver', 'cleanup']), State('playBackPatterns', self.enterPlayBackPatterns, self.exitPlayBackPatterns, ['checkGameOver', 'cleanup']),
State.State('checkGameOver', self.enterCheckGameOver, self.exitCheckGameOver, ['waitForServerPattern', 'cleanup']), State('checkGameOver', self.enterCheckGameOver, self.exitCheckGameOver, ['waitForServerPattern', 'cleanup']),
State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup')
self.addChildGameFSM(self.gameFSM) self.addChildGameFSM(self.gameFSM)
self.arrowColor = VBase4(1, 0, 0, 1) self.arrowColor = VBase4(1, 0, 0, 1)
self.xColor = VBase4(1, 0, 0, 1) self.xColor = VBase4(1, 0, 0, 1)
@ -63,7 +77,6 @@ class DistributedPatternGame(DistributedMinigame):
self.opaq = VBase4(1, 0, 0, 1) self.opaq = VBase4(1, 0, 0, 1)
self.normalTextColor = VBase4(0.537, 0.84, 0.33, 1.0) self.normalTextColor = VBase4(0.537, 0.84, 0.33, 1.0)
self.__otherToonIndex = {} self.__otherToonIndex = {}
return
def getTitle(self): def getTitle(self):
return TTLocalizer.PatternGameTitle return TTLocalizer.PatternGameTitle
@ -78,10 +91,10 @@ class DistributedPatternGame(DistributedMinigame):
def load(self): def load(self):
self.notify.debug('load') self.notify.debug('load')
DistributedMinigame.load(self) DistributedMinigame.load(self)
self.timer = ToontownTimer.ToontownTimer() self.timer = ToontownTimer()
self.timer.posInTopRightCorner() self.timer.posInTopRightCorner()
self.timer.hide() self.timer.hide()
self.room = loader.loadModel('phase_4/models/minigames/matching_room') self.room = base.loader.loadModel('phase_4/models/minigames/matching_room')
self.buttonSounds = [] self.buttonSounds = []
for soundName in self.ButtonSoundNames: for soundName in self.ButtonSoundNames:
self.buttonSounds.append(base.loader.loadSfx(soundName)) self.buttonSounds.append(base.loader.loadSfx(soundName))
@ -95,18 +108,18 @@ class DistributedPatternGame(DistributedMinigame):
self.roundText = DirectLabel(text=self.strRound % 1, text_fg=self.normalTextColor, frameColor=(1, 1, 1, 0), text_font=ToontownGlobals.getSignFont(), pos=(0.014, 0, -.84), scale=0.12) self.roundText = DirectLabel(text=self.strRound % 1, text_fg=self.normalTextColor, frameColor=(1, 1, 1, 0), text_font=ToontownGlobals.getSignFont(), pos=(0.014, 0, -.84), scale=0.12)
self.roundText.hide() self.roundText.hide()
self.waitingText.hide() self.waitingText.hide()
matchingGameGui = loader.loadModel('phase_3.5/models/gui/matching_game_gui') matchingGameGui = base.loader.loadModel('phase_3.5/models/gui/matching_game_gui')
minnieArrow = matchingGameGui.find('**/minnieArrow') minnieArrow = matchingGameGui.find('**/minnieArrow')
minnieX = matchingGameGui.find('**/minnieX') minnieX = matchingGameGui.find('**/minnieX')
minnieCircle = matchingGameGui.find('**/minnieCircle') minnieCircle = matchingGameGui.find('**/minnieCircle')
self.arrows = [None] * 5 self.arrows = [None] * 5
for x in range(0, 5): for x in range(0, 5):
self.arrows[x] = minnieArrow.copyTo(hidden) self.arrows[x] = minnieArrow.copyTo(base.hidden)
self.arrows[x].hide() self.arrows[x].hide()
self.xs = [None] * 5 self.xs = [None] * 5
for x in range(0, 5): for x in range(0, 5):
self.xs[x] = minnieX.copyTo(hidden) self.xs[x] = minnieX.copyTo(base.hidden)
self.xs[x].hide() self.xs[x].hide()
self.statusBalls = [] self.statusBalls = []
@ -116,20 +129,20 @@ class DistributedPatternGame(DistributedMinigame):
for x in range(0, 4): for x in range(0, 4):
for y in range(0, self.totalMoves): for y in range(0, self.totalMoves):
self.statusBalls[x][y] = minnieCircle.copyTo(hidden) self.statusBalls[x][y] = minnieCircle.copyTo(base.hidden)
self.statusBalls[x][y].hide() self.statusBalls[x][y].hide()
minnieArrow.removeNode() minnieArrow.removeNode()
minnieX.removeNode() minnieX.removeNode()
minnieCircle.removeNode() minnieCircle.removeNode()
matchingGameGui.removeNode() matchingGameGui.removeNode()
self.minnie = Char.Char() self.minnie = Char()
m = self.minnie m = self.minnie
dna = CharDNA.CharDNA() dna = CharDNA()
dna.newChar('mn') dna.newChar('mn')
m.setDNA(dna) m.setDNA(dna)
m.setName(TTLocalizer.Minnie) m.setName(TTLocalizer.Minnie)
m.reparentTo(hidden) m.reparentTo(base.hidden)
self.backRowHome = Point3(3, 11, 0) self.backRowHome = Point3(3, 11, 0)
self.backRowXSpacing = 1.8 self.backRowXSpacing = 1.8
self.frontRowHome = Point3(0, 18, 0) self.frontRowHome = Point3(0, 18, 0)
@ -140,12 +153,10 @@ class DistributedPatternGame(DistributedMinigame):
self.animPlayRates = [] self.animPlayRates = []
animPlayRate = 1.4 animPlayRate = 1.4
animPlayRateMult = 1.06 animPlayRateMult = 1.06
for i in range(PatternGameGlobals.NUM_ROUNDS): for _ in range(PatternGameGlobals.NUM_ROUNDS):
self.animPlayRates.append(animPlayRate) self.animPlayRates.append(animPlayRate)
animPlayRate *= animPlayRateMult animPlayRate *= animPlayRateMult
return
def unload(self): def unload(self):
self.notify.debug('unload') self.notify.debug('unload')
DistributedMinigame.unload(self) DistributedMinigame.unload(self)
@ -201,12 +212,12 @@ class DistributedPatternGame(DistributedMinigame):
DistributedMinigame.onstage(self) DistributedMinigame.onstage(self)
self.arrowDict = {} self.arrowDict = {}
self.lt = base.localAvatar self.lt = base.localAvatar
camera.reparentTo(render) base.camera.reparentTo(base.render)
camera.setPosHpr(0.0, -14.59, 10.56, 0.0, -16.39, 0.0) base.camera.setPosHpr(0.0, -14.59, 10.56, 0.0, -16.39, 0.0)
base.camLens.setFov(24.66) base.camLens.setFov(24.66)
NametagGlobals.setGlobalNametagScale(0.6) NametagGlobals.setGlobalNametagScale(0.6)
self.arrowKeys = ArrowKeys.ArrowKeys() self.arrowKeys = ArrowKeys()
self.room.reparentTo(render) self.room.reparentTo(base.render)
self.room.setPosHpr(0.0, 18.39, -ToontownGlobals.FloorOffset, 0.0, 0.0, 0.0) self.room.setPosHpr(0.0, 18.39, -ToontownGlobals.FloorOffset, 0.0, 0.0, 0.0)
self.room.setScale(1) self.room.setScale(1)
for anim in self.minnieAnimNames: for anim in self.minnieAnimNames:
@ -226,7 +237,7 @@ class DistributedPatternGame(DistributedMinigame):
self.toonAnimSpeedMult[anim] = float(self.__numPingPongFrames(numFrames)) / float(self.stdNumDanceStepPingPongFrames) self.toonAnimSpeedMult[anim] = float(self.__numPingPongFrames(numFrames)) / float(self.stdNumDanceStepPingPongFrames)
lt = self.lt lt = self.lt
lt.reparentTo(render) lt.reparentTo(base.render)
lt.useLOD(1000) lt.useLOD(1000)
lt.setPos(-3.5, 11, 0.0) lt.setPos(-3.5, 11, 0.0)
lt.setScale(1) lt.setScale(1)
@ -246,11 +257,12 @@ class DistributedPatternGame(DistributedMinigame):
else: else:
self.arrowDict['lt'][k].setScale(4, 4, 4) self.arrowDict['lt'][k].setScale(4, 4, 4)
self.arrowDict['lt'][k].setColor(self.xColor) self.arrowDict['lt'][k].setColor(self.xColor)
self.arrowDict['lt'][k].setPos(0, 0, 1) self.arrowDict['lt'][k].setPos(0, 0, 1)
self.formatStatusBalls(self.arrowDict['lt'][2], jj) self.formatStatusBalls(self.arrowDict['lt'][2], jj)
m = self.minnie m = self.minnie
m.reparentTo(render) m.reparentTo(base.render)
m.setPos(-1.6, 20, 0) m.setPos(-1.6, 20, 0)
m.setScale(1) m.setScale(1)
self.makeToonLookatCamera(m) self.makeToonLookatCamera(m)
@ -280,13 +292,13 @@ class DistributedPatternGame(DistributedMinigame):
NametagGlobals.setGlobalNametagScale(1.0) NametagGlobals.setGlobalNametagScale(1.0)
self.arrowKeys.destroy() self.arrowKeys.destroy()
del self.arrowKeys del self.arrowKeys
self.room.reparentTo(hidden) self.room.reparentTo(base.hidden)
self.roundText.hide() self.roundText.hide()
self.minnie.nametag.unmanage(base.marginManager) self.minnie.nametag.unmanage(base.marginManager)
self.minnie.stopEarTask() self.minnie.stopEarTask()
self.minnie.stop() self.minnie.stop()
self.minnie.stopBlink() self.minnie.stopBlink()
self.minnie.reparentTo(hidden) self.minnie.reparentTo(base.hidden)
self.lt.setScale(1) self.lt.setScale(1)
for avId in self.remoteAvIdList: for avId in self.remoteAvIdList:
toon = self.getAvatar(avId) toon = self.getAvatar(avId)
@ -303,9 +315,11 @@ class DistributedPatternGame(DistributedMinigame):
def setGameReady(self): def setGameReady(self):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
self.notify.debug('setGameReady') self.notify.debug('setGameReady')
if DistributedMinigame.setGameReady(self): if DistributedMinigame.setGameReady(self):
return return
for avId in self.remoteAvIdList: for avId in self.remoteAvIdList:
toon = self.getAvatar(avId) toon = self.getAvatar(avId)
if toon: if toon:
@ -321,10 +335,11 @@ class DistributedPatternGame(DistributedMinigame):
else: else:
self.arrowDict[avId][k].setScale(4, 4, 4) self.arrowDict[avId][k].setScale(4, 4, 4)
self.arrowDict[avId][k].setColor(self.xColor) self.arrowDict[avId][k].setColor(self.xColor)
self.arrowDict[avId][k].setPos(0, 0, 1) self.arrowDict[avId][k].setPos(0, 0, 1)
self.formatStatusBalls(self.arrowDict[avId][2], jj) self.formatStatusBalls(self.arrowDict[avId][2], jj)
toon.reparentTo(render) toon.reparentTo(base.render)
toon.useLOD(1000) toon.useLOD(1000)
toon.setPos(self.getBackRowPos(avId)) toon.setPos(self.getBackRowPos(avId))
toon.setScale(0.9) toon.setScale(0.9)
@ -338,16 +353,17 @@ class DistributedPatternGame(DistributedMinigame):
self.waitingText['text'] = self.strPleaseWait self.waitingText['text'] = self.strPleaseWait
else: else:
self.waitingText['text'] = self.strWaitingOtherPlayers self.waitingText['text'] = self.strWaitingOtherPlayers
self.animTracks = {} self.animTracks = {}
for avId in self.avIdList: for avId in self.avIdList:
self.animTracks[avId] = None self.animTracks[avId] = None
self.__initGameVars() self.__initGameVars()
return
def setGameStart(self, timestamp): def setGameStart(self, timestamp):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
self.notify.debug('setGameStart') self.notify.debug('setGameStart')
DistributedMinigame.setGameStart(self, timestamp) DistributedMinigame.setGameStart(self, timestamp)
self.gameFSM.request('waitForServerPattern') self.gameFSM.request('waitForServerPattern')
@ -360,7 +376,7 @@ class DistributedPatternGame(DistributedMinigame):
return numFrames * 2 - 1 return numFrames * 2 - 1
def makeToonLookatCamera(self, toon): def makeToonLookatCamera(self, toon):
toon.headsUp(camera) toon.headsUp(base.camera)
def setText(self, t, newtext): def setText(self, t, newtext):
t['text'] = newtext t['text'] = newtext
@ -376,6 +392,7 @@ class DistributedPatternGame(DistributedMinigame):
if startPos: if startPos:
toon.setPos(startPos) toon.setPos(startPos)
track.append(Func(toon.setPos, startPos)) track.append(Func(toon.setPos, startPos))
for endPos in posList: for endPos in posList:
toon.headsUp(Point3(endPos)) toon.headsUp(Point3(endPos))
track.append(Func(toon.setHpr, Point3(toon.getH(), 0, 0))) track.append(Func(toon.setHpr, Point3(toon.getH(), 0, 0)))
@ -387,14 +404,16 @@ class DistributedPatternGame(DistributedMinigame):
if lookAtCam: if lookAtCam:
saveHpr = toon.getHpr() saveHpr = toon.getHpr()
toon.headsUp(camera) toon.headsUp(base.camera)
endHeading = toon.getHpr()[0] endHeading = toon.getHpr()[0]
toon.setHpr(saveHpr) toon.setHpr(saveHpr)
curHeading = toon.getH() curHeading = toon.getH()
if endHeading - curHeading > 180.0: if endHeading - curHeading > 180.0:
endHeading -= 360 endHeading -= 360
elif endHeading - curHeading < -180.0: elif endHeading - curHeading < -180.0:
endHeading += 360 endHeading += 360
endHpr = Point3(endHeading, 0, 0) endHpr = Point3(endHeading, 0, 0)
duration = abs(endHeading - curHeading) / 180.0 * 0.3 duration = abs(endHeading - curHeading) / 180.0 * 0.3
track.extend([Func(toon.loop, 'walk'), LerpHprInterval(toon, duration, endHpr), Func(toon.loop, 'neutral')]) track.extend([Func(toon.loop, 'walk'), LerpHprInterval(toon, duration, endHpr), Func(toon.loop, 'neutral')])
@ -456,6 +475,7 @@ class DistributedPatternGame(DistributedMinigame):
ri.append(ActorInterval(actor=self.lt, animName='victory', duration=5.5)) ri.append(ActorInterval(actor=self.lt, animName='victory', duration=5.5))
else: else:
ri.append(Func(self.lt.loop, 'neutral')) ri.append(Func(self.lt.loop, 'neutral'))
for avId in self.remoteAvIdList: for avId in self.remoteAvIdList:
toon = self.getAvatar(avId) toon = self.getAvatar(avId)
if toon: if toon:
@ -503,18 +523,21 @@ class DistributedPatternGame(DistributedMinigame):
track = Sequence(Func(self.changeArrow, toonID, index), Wait(wait)) track = Sequence(Func(self.changeArrow, toonID, index), Wait(wait))
else: else:
track = Sequence(Func(self.changeArrow, toonID, index), Wait(wait), LerpColorInterval(self.arrowDict[toonID][0], d, self.trans, self.opaq)) track = Sequence(Func(self.changeArrow, toonID, index), Wait(wait), LerpColorInterval(self.arrowDict[toonID][0], d, self.trans, self.opaq))
return track return track
def getDanceSequenceAnimTrack(self, toon, pattern): def getDanceSequenceAnimTrack(self, toon, pattern):
getDanceStepTrack = self.__getToonDanceStepAnimTrack getDanceStepTrack = self.__getToonDanceStepAnimTrack
if toon == self.minnie: if toon == self.minnie:
getDanceStepTrack = self.__getMinnieDanceStepAnimTrack getDanceStepTrack = self.__getMinnieDanceStepAnimTrack
tracks = Sequence() tracks = Sequence()
for direction in pattern: for direction in pattern:
tracks.append(getDanceStepTrack(toon, direction)) tracks.append(getDanceStepTrack(toon, direction))
if len(pattern): if len(pattern):
tracks.append(Func(toon.loop, 'neutral')) tracks.append(Func(toon.loop, 'neutral'))
return tracks return tracks
def getDanceSequenceButtonSoundTrack(self, pattern): def getDanceSequenceButtonSoundTrack(self, pattern):
@ -558,6 +581,7 @@ class DistributedPatternGame(DistributedMinigame):
def setPattern(self, pattern): def setPattern(self, pattern):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
self.notify.debug('setPattern: ' + str(pattern)) self.notify.debug('setPattern: ' + str(pattern))
self.__serverPattern = pattern self.__serverPattern = pattern
self.gameFSM.request('showServerPattern') self.gameFSM.request('showServerPattern')
@ -591,6 +615,7 @@ class DistributedPatternGame(DistributedMinigame):
def exitShowServerPattern(self): def exitShowServerPattern(self):
if self.showTrack.isPlaying(): if self.showTrack.isPlaying():
self.showTrack.pause() self.showTrack.pause()
del self.showTrack del self.showTrack
def enterGetUserInput(self): def enterGetUserInput(self):
@ -599,7 +624,7 @@ class DistributedPatternGame(DistributedMinigame):
self.proceedTrack = None self.proceedTrack = None
def startTimer(self = self): def startTimer(self = self):
self.currentStartTime = globalClock.getFrameTime() self.currentStartTime = base.clock.getFrameTime()
self.timer.show() self.timer.show()
self.timer.countdown(PatternGameGlobals.InputTime, self.__handleInputTimeout) self.timer.countdown(PatternGameGlobals.InputTime, self.__handleInputTimeout)
@ -629,7 +654,6 @@ class DistributedPatternGame(DistributedMinigame):
self.setupTrack = Sequence(Func(self.__setMinnieChat, self.strGo, 0), Func(self.setText, self.roundText, TTLocalizer.PatternGameGo), Func(self.roundText.setScale, 0.3), Func(enableKeys), Func(startTimer), Wait(0.8), Func(self.__clearMinnieChat), Func(self.setText, self.roundText, ' '), Func(self.roundText.setScale, 0.12), Func(self.setTextFG, self.roundText, self.normalTextColor)) self.setupTrack = Sequence(Func(self.__setMinnieChat, self.strGo, 0), Func(self.setText, self.roundText, TTLocalizer.PatternGameGo), Func(self.roundText.setScale, 0.3), Func(enableKeys), Func(startTimer), Wait(0.8), Func(self.__clearMinnieChat), Func(self.setText, self.roundText, ' '), Func(self.roundText.setScale, 0.12), Func(self.setTextFG, self.roundText, self.normalTextColor))
self.setupTrack.start() self.setupTrack.start()
return
def __handleInputTimeout(self): def __handleInputTimeout(self):
self.__doneGettingInput(self.__localPattern) self.__doneGettingInput(self.__localPattern)
@ -643,15 +667,18 @@ class DistributedPatternGame(DistributedMinigame):
def remoteButtonPressed(self, avId, index, wrong): def remoteButtonPressed(self, avId, index, wrong):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
if self.gameFSM.getCurrentState().getName() not in ['getUserInput', 'waitForPlayerPatterns']: if self.gameFSM.getCurrentState().getName() not in ['getUserInput', 'waitForPlayerPatterns']:
return return
if avId != self.localAvId: if avId != self.localAvId:
if self.animTracks[avId]: if self.animTracks[avId]:
self.animTracks[avId].finish() self.animTracks[avId].finish()
av = self.getAvatar(avId) av = self.getAvatar(avId)
if wrong: if wrong:
acts = ['slip-forward', 'slip-backward'] acts = ['slip-forward', 'slip-backward']
ag = random.choice(acts) ag = choice(acts)
self.arrowDict[avId][0].hide() self.arrowDict[avId][0].hide()
self.animTracks[avId] = Sequence(Func(self.showX, avId), Func(self.colorStatusBall, avId, self.__otherToonIndex[avId], 0), ActorInterval(actor=av, animName=ag, duration=2.35), Func(av.loop, 'neutral'), Func(self.hideX, avId)) self.animTracks[avId] = Sequence(Func(self.showX, avId), Func(self.colorStatusBall, avId, self.__otherToonIndex[avId], 0), ActorInterval(actor=av, animName=ag, duration=2.35), Func(av.loop, 'neutral'), Func(self.hideX, avId))
else: else:
@ -659,6 +686,7 @@ class DistributedPatternGame(DistributedMinigame):
arrowTrack = self.getDanceArrowAnimTrack(avId, [index], 1) arrowTrack = self.getDanceArrowAnimTrack(avId, [index], 1)
potTrack = self.getDanceSequenceAnimTrack(av, [index]) potTrack = self.getDanceSequenceAnimTrack(av, [index])
self.animTracks[avId] = Parallel(potTrack, arrowTrack) self.animTracks[avId] = Parallel(potTrack, arrowTrack)
self.__otherToonIndex[avId] += 1 self.__otherToonIndex[avId] += 1
self.animTracks[avId].start() self.animTracks[avId].start()
@ -668,13 +696,15 @@ class DistributedPatternGame(DistributedMinigame):
def __buttonPressed(self, index): def __buttonPressed(self, index):
if len(self.__localPattern) >= len(self.__serverPattern): if len(self.__localPattern) >= len(self.__serverPattern):
return return
if self.animTracks[self.localAvId]: if self.animTracks[self.localAvId]:
self.animTracks[self.localAvId].finish() self.animTracks[self.localAvId].finish()
badd = 0 badd = 0
if index != self.__serverPattern[len(self.__localPattern)]: if index != self.__serverPattern[len(self.__localPattern)]:
badd = 1 badd = 1
acts = ['slip-forward', 'slip-backward'] acts = ['slip-forward', 'slip-backward']
ag = random.choice(acts) ag = choice(acts)
self.animTracks[self.localAvId] = Sequence(Func(self.showX, 'lt'), Func(self.colorStatusBall, 'lt', len(self.__localPattern), 0), ActorInterval(actor=self.lt, animName=ag, duration=2.35), Func(self.lt.loop, 'neutral'), Func(self.hideX, 'lt')) self.animTracks[self.localAvId] = Sequence(Func(self.showX, 'lt'), Func(self.colorStatusBall, 'lt', len(self.__localPattern), 0), ActorInterval(actor=self.lt, animName=ag, duration=2.35), Func(self.lt.loop, 'neutral'), Func(self.hideX, 'lt'))
self.arrowDict['lt'][0].hide() self.arrowDict['lt'][0].hide()
base.playSfx(self.fallSound) base.playSfx(self.fallSound)
@ -684,6 +714,7 @@ class DistributedPatternGame(DistributedMinigame):
arrowTrack = self.getDanceArrowAnimTrack('lt', [index], 1) arrowTrack = self.getDanceArrowAnimTrack('lt', [index], 1)
potTrack = self.getDanceSequenceAnimTrack(self.lt, [index]) potTrack = self.getDanceSequenceAnimTrack(self.lt, [index])
self.animTracks[self.localAvId] = Parallel(potTrack, arrowTrack) self.animTracks[self.localAvId] = Parallel(potTrack, arrowTrack)
self.sendUpdate('reportButtonPress', [index, badd]) self.sendUpdate('reportButtonPress', [index, badd])
self.animTracks[self.localAvId].start() self.animTracks[self.localAvId].start()
self.__localPattern.append(index) self.__localPattern.append(index)
@ -692,7 +723,7 @@ class DistributedPatternGame(DistributedMinigame):
def __doneGettingInput(self, pattern): def __doneGettingInput(self, pattern):
self.arrowKeys.setPressHandlers(self.arrowKeys.NULL_HANDLERS) self.arrowKeys.setPressHandlers(self.arrowKeys.NULL_HANDLERS)
self.currentTotalTime = globalClock.getFrameTime() - self.currentStartTime self.currentTotalTime = base.clock.getFrameTime() - self.currentStartTime
self.proceedTrack = Sequence(Wait(self.getDanceStepDuration()), Func(self.sendUpdate, 'reportPlayerPattern', [pattern, self.currentTotalTime]), Func(self.gameFSM.request, 'waitForPlayerPatterns')) self.proceedTrack = Sequence(Wait(self.getDanceStepDuration()), Func(self.sendUpdate, 'reportPlayerPattern', [pattern, self.currentTotalTime]), Func(self.gameFSM.request, 'waitForPlayerPatterns'))
self.proceedTrack.start() self.proceedTrack.start()
@ -703,8 +734,10 @@ class DistributedPatternGame(DistributedMinigame):
self.arrowKeys.setReleaseHandlers(self.arrowKeys.NULL_HANDLERS) self.arrowKeys.setReleaseHandlers(self.arrowKeys.NULL_HANDLERS)
if self.setupTrack and self.setupTrack.isPlaying(): if self.setupTrack and self.setupTrack.isPlaying():
self.setupTrack.pause() self.setupTrack.pause()
if self.proceedTrack and self.proceedTrack.isPlaying(): if self.proceedTrack and self.proceedTrack.isPlaying():
self.proceedTrack.pause() self.proceedTrack.pause()
del self.setupTrack del self.setupTrack
del self.proceedTrack del self.proceedTrack
self.__clearMinnieChat() self.__clearMinnieChat()
@ -715,6 +748,7 @@ class DistributedPatternGame(DistributedMinigame):
def setPlayerPatterns(self, pattern1, pattern2, pattern3, pattern4, fastestAvId): def setPlayerPatterns(self, pattern1, pattern2, pattern3, pattern4, fastestAvId):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
self.fastestAvId = fastestAvId self.fastestAvId = fastestAvId
self.notify.debug('setPlayerPatterns:' + ' pattern1:' + str(pattern1) + ' pattern2:' + str(pattern2) + ' pattern3:' + str(pattern3) + ' pattern4:' + str(pattern4)) self.notify.debug('setPlayerPatterns:' + ' pattern1:' + str(pattern1) + ' pattern2:' + str(pattern2) + ' pattern3:' + str(pattern3) + ' pattern4:' + str(pattern4))
self.playerPatterns = {} self.playerPatterns = {}
@ -738,6 +772,7 @@ class DistributedPatternGame(DistributedMinigame):
self.roundText['text'] = TTLocalizer.PatternGameFastest self.roundText['text'] = TTLocalizer.PatternGameFastest
else: else:
self.roundText['text'] = TTLocalizer.PatternGameFaster self.roundText['text'] = TTLocalizer.PatternGameFaster
jumpTrack = Sequence(ActorInterval(actor=self.lt, animName='jump', duration=1.7), Func(self.lt.loop, 'neutral')) jumpTrack = Sequence(ActorInterval(actor=self.lt, animName='jump', duration=1.7), Func(self.lt.loop, 'neutral'))
elif self.fastestAvId == 0: elif self.fastestAvId == 0:
if self.round == PatternGameGlobals.NUM_ROUNDS: if self.round == PatternGameGlobals.NUM_ROUNDS:
@ -745,6 +780,7 @@ class DistributedPatternGame(DistributedMinigame):
else: else:
self.roundText.setScale(0.1) self.roundText.setScale(0.1)
self.roundText['text'] = TTLocalizer.PatternGameYouCanDoIt self.roundText['text'] = TTLocalizer.PatternGameYouCanDoIt
jumpTrack = Sequence(Wait(0.5), Wait(0.5)) jumpTrack = Sequence(Wait(0.5), Wait(0.5))
elif self.fastestAvId == 1: elif self.fastestAvId == 1:
self.roundText.setScale(0.1) self.roundText.setScale(0.1)
@ -758,7 +794,9 @@ class DistributedPatternGame(DistributedMinigame):
rewardStr = TTLocalizer.PatternGameOtherFastest rewardStr = TTLocalizer.PatternGameOtherFastest
else: else:
rewardStr = TTLocalizer.PatternGameOtherFaster rewardStr = TTLocalizer.PatternGameOtherFaster
self.roundText['text'] = av.getName() + rewardStr self.roundText['text'] = av.getName() + rewardStr
success = self.playerPatterns[self.localAvId] == self.__serverPattern success = self.playerPatterns[self.localAvId] == self.__serverPattern
self.hideStatusBalls('lt') self.hideStatusBalls('lt')
for avId in self.remoteAvIdList: for avId in self.remoteAvIdList:
@ -771,6 +809,7 @@ class DistributedPatternGame(DistributedMinigame):
self.perfectGame = 0 self.perfectGame = 0
sound = self.incorrectSound sound = self.incorrectSound
text = self.strWrong text = self.strWrong
soundTrack = Sequence(Func(base.playSfx, sound), Wait(1.6)) soundTrack = Sequence(Func(base.playSfx, sound), Wait(1.6))
textTrack = Sequence(Wait(0.2), Func(self.__setMinnieChat, text, 0), Wait(1.3), Func(self.__clearMinnieChat)) textTrack = Sequence(Wait(0.2), Func(self.__setMinnieChat, text, 0), Wait(1.3), Func(self.__clearMinnieChat))
self.playBackPatternsTrack = Sequence(Parallel(soundTrack, textTrack, jumpTrack), Func(self.gameFSM.request, 'checkGameOver')) self.playBackPatternsTrack = Sequence(Parallel(soundTrack, textTrack, jumpTrack), Func(self.gameFSM.request, 'checkGameOver'))
@ -779,6 +818,7 @@ class DistributedPatternGame(DistributedMinigame):
def exitPlayBackPatterns(self): def exitPlayBackPatterns(self):
if self.playBackPatternsTrack.isPlaying(): if self.playBackPatternsTrack.isPlaying():
self.playBackPatternsTrack.pause() self.playBackPatternsTrack.pause()
del self.playBackPatternsTrack del self.playBackPatternsTrack
def enterCheckGameOver(self): def enterCheckGameOver(self):
@ -794,17 +834,19 @@ class DistributedPatternGame(DistributedMinigame):
text = self.strPerfect text = self.strPerfect
sound = self.perfectSound sound = self.perfectSound
delay = 2.2 delay = 2.2
if self.celebrate: if self.celebrate:
text = TTLocalizer.PatternGameImprov text = TTLocalizer.PatternGameImprov
self.__winTrack = Sequence(Func(self.__setMinnieChat, text, 1), Func(base.playSfx, self.perfectSound), Sequence(self.returnCelebrationIntervals(1)), Sequence(self.returnCelebrationIntervals(0)), Func(self.__clearMinnieChat), Func(self.gameOver)) self.__winTrack = Sequence(Func(self.__setMinnieChat, text, 1), Func(base.playSfx, self.perfectSound), Sequence(self.returnCelebrationIntervals(1)), Sequence(self.returnCelebrationIntervals(0)), Func(self.__clearMinnieChat), Func(self.gameOver))
else: else:
self.__winTrack = Sequence(Func(self.__setMinnieChat, text, 1), Func(base.playSfx, sound), Wait(delay), Func(self.__clearMinnieChat), Func(self.gameOver)) self.__winTrack = Sequence(Func(self.__setMinnieChat, text, 1), Func(base.playSfx, sound), Wait(delay), Func(self.__clearMinnieChat), Func(self.gameOver))
self.__winTrack.start() self.__winTrack.start()
return
def exitCheckGameOver(self): def exitCheckGameOver(self):
if self.__winTrack and self.__winTrack.isPlaying(): if self.__winTrack and self.__winTrack.isPlaying():
self.__winTrack.pause() self.__winTrack.pause()
del self.__winTrack del self.__winTrack
def enterCleanup(self): def enterCleanup(self):

View file

@ -1,30 +1,42 @@
from panda3d.core import * from panda3d.core import RopeNode, VBase3
from toontown.toonbase.ToonBaseGlobal import * from panda3d.otp import NametagGlobals
from direct.interval.IntervalGlobal import *
from .DistributedMinigame import * from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.gui.DirectGui import * from direct.fsm.ClassicFSM import ClassicFSM
from panda3d.core import * from direct.fsm.State import State
from direct.fsm import ClassicFSM, State from direct.gui.DirectGui import DGG, DirectLabel
from direct.fsm import State from direct.interval.IntervalGlobal import (
from toontown.toonbase import ToontownTimer ActorInterval,
from toontown.toon import ToonHead Func,
from toontown.suit import SuitDNA LerpHprInterval,
from toontown.suit import Suit LerpPosInterval,
from toontown.char import Char LerpPosHprInterval,
from . import ArrowKeys Parallel,
import random Sequence,
Wait
)
from direct.showutil.Rope import Rope
from direct.task.TaskManagerGlobal import taskMgr
from toontown.effects.Ripples import Ripples
from toontown.effects.Splash import Splash
from toontown.minigame import TugOfWarGameGlobals
from toontown.minigame.ArrowKeys import ArrowKeys
from toontown.minigame.DistributedMinigame import DistributedMinigame
from toontown.minigame.MinigamePowerMeter import MinigamePowerMeter
from toontown.suit.Suit import Suit
from toontown.suit.SuitDNA import SuitDNA
from toontown.toonbase import ToontownGlobals from toontown.toonbase import ToontownGlobals
import string
from toontown.toonbase import TTLocalizer from toontown.toonbase import TTLocalizer
from . import TugOfWarGameGlobals from toontown.toonbase.ToonBaseGlobal import base
from direct.showutil import Rope from toontown.toonbase.ToontownTimer import ToontownTimer
from toontown.effects import Splash
from toontown.effects import Ripples import math
from toontown.toonbase import TTLocalizer
from . import MinigamePowerMeter
from direct.task.Task import Task
class DistributedTugOfWarGame(DistributedMinigame): class DistributedTugOfWarGame(DistributedMinigame):
notify = directNotify.newCategory('DistributedTugOfWarGame')
bgm = 'phase_4/audio/bgm/MG_tug_o_war.ogg' bgm = 'phase_4/audio/bgm/MG_tug_o_war.ogg'
toonAnimNames = ['neutral', toonAnimNames = ['neutral',
'tug-o-war', 'tug-o-war',
@ -46,11 +58,11 @@ class DistributedTugOfWarGame(DistributedMinigame):
def __init__(self, cr): def __init__(self, cr):
DistributedMinigame.__init__(self, cr) DistributedMinigame.__init__(self, cr)
self.gameFSM = ClassicFSM.ClassicFSM('DistributedTugOfWarGame', [State.State('off', self.enterOff, self.exitOff, ['waitForGoSignal']), self.gameFSM = ClassicFSM('DistributedTugOfWarGame', [State('off', self.enterOff, self.exitOff, ['waitForGoSignal']),
State.State('waitForGoSignal', self.enterWaitForGoSignal, self.exitWaitForGoSignal, ['tug', 'cleanup']), State('waitForGoSignal', self.enterWaitForGoSignal, self.exitWaitForGoSignal, ['tug', 'cleanup']),
State.State('tug', self.enterTug, self.exitTug, ['gameDone', 'cleanup']), State('tug', self.enterTug, self.exitTug, ['gameDone', 'cleanup']),
State.State('gameDone', self.enterGameDone, self.exitGameDone, ['cleanup']), State('gameDone', self.enterGameDone, self.exitGameDone, ['cleanup']),
State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup')
self.addChildGameFSM(self.gameFSM) self.addChildGameFSM(self.gameFSM)
self.gameType = TugOfWarGameGlobals.TOON_VS_TOON self.gameType = TugOfWarGameGlobals.TOON_VS_TOON
self.suit = None self.suit = None
@ -92,13 +104,11 @@ class DistributedTugOfWarGame(DistributedMinigame):
for k in range(4): for k in range(4):
self.drinkPositions.append(VBase3(-.2 + 0.2 * k, 16 + 2 * k, 0.0)) self.drinkPositions.append(VBase3(-.2 + 0.2 * k, 16 + 2 * k, 0.0))
self.rng = RandomNumGen.RandomNumGen(1000)
self.introTrack = None self.introTrack = None
self.showTrack = None self.showTrack = None
self.setupTrack = None self.setupTrack = None
self.animTracks = {} self.animTracks = {}
self.randomNumGen = None self.randomNumGen = None
return
def getTitle(self): def getTitle(self):
return TTLocalizer.TugOfWarGameTitle return TTLocalizer.TugOfWarGameTitle
@ -112,40 +122,39 @@ class DistributedTugOfWarGame(DistributedMinigame):
def load(self): def load(self):
self.notify.debug('load') self.notify.debug('load')
DistributedMinigame.load(self) DistributedMinigame.load(self)
self.timer = ToontownTimer.ToontownTimer() self.timer = ToontownTimer()
self.timer.posInTopRightCorner() self.timer.posInTopRightCorner()
self.timer.hide() self.timer.hide()
self.room = loader.loadModel('phase_4/models/minigames/tug_of_war_dock') self.room = base.loader.loadModel('phase_4/models/minigames/tug_of_war_dock')
self.room.reparentTo(hidden) self.room.reparentTo(base.hidden)
ropeModel = loader.loadModel('phase_4/models/minigames/tug_of_war_rope') ropeModel = base.loader.loadModel('phase_4/models/minigames/tug_of_war_rope')
self.ropeTexture = ropeModel.findTexture('*') self.ropeTexture = ropeModel.findTexture('*')
ropeModel.removeNode() ropeModel.removeNode()
self.sky = loader.loadModel('phase_3.5/models/props/TT_sky') self.sky = base.loader.loadModel('phase_3.5/models/props/TT_sky')
self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow') self.dropShadow = base.loader.loadModel('phase_3/models/props/drop_shadow')
self.correctSound = base.loader.loadSfx('phase_4/audio/sfx/MG_pos_buzzer.ogg') 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.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.whistleSound = base.loader.loadSfx('phase_4/audio/sfx/AA_sound_whistle.ogg')
self.music = base.loader.loadMusic(self.bgm) 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.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 = MinigamePowerMeter(17)
self.powerMeter.reparentTo(aspect2d) self.powerMeter.reparentTo(base.aspect2d)
self.powerMeter.setPos(0, 0, 0.4) self.powerMeter.setPos(0, 0, 0.4)
self.powerMeter.setPower(8) self.powerMeter.setPower(8)
self.powerMeter.setTarget(8) self.powerMeter.setTarget(8)
self.arrows = [None] * 2 self.arrows = [None] * 2
for x in range(len(self.arrows)): for x in range(len(self.arrows)):
self.arrows[x] = loader.loadModel('phase_3/models/props/arrow') self.arrows[x] = base.loader.loadModel('phase_3/models/props/arrow')
self.arrows[x].reparentTo(self.powerMeter) self.arrows[x].reparentTo(self.powerMeter)
self.arrows[x].hide() self.arrows[x].hide()
self.arrows[x].setScale(0.2 - 0.4 * x, 0.2, 0.2) 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.arrows[x].setPos(0.12 - 0.24 * x, 0, -.26)
self.disableArrow(self.arrows[x]) self.disableArrow(self.arrows[x])
self.splash = Splash.Splash(render) self.splash = Splash(base.render)
self.suitSplash = Splash.Splash(render) self.suitSplash = Splash(base.render)
self.ripples = Ripples.Ripples(render) self.ripples = Ripples(base.render)
self.suitRipples = Ripples.Ripples(render) self.suitRipples = Ripples(base.render)
return
def toggleMouseMode(self, param): def toggleMouseMode(self, param):
self.mouseMode = not self.mouseMode self.mouseMode = not self.mouseMode
@ -155,6 +164,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.hilightArrow(self.arrows[1]) self.hilightArrow(self.arrows[1])
else: else:
self.hilightArrow(self.arrows[0]) self.hilightArrow(self.arrows[0])
self.__spawnMouseSpeedTask() self.__spawnMouseSpeedTask()
else: else:
self.__releaseHandler(0) self.__releaseHandler(0)
@ -183,6 +193,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.powerMeter: if self.powerMeter:
self.powerMeter.destroy() self.powerMeter.destroy()
del self.powerMeter del self.powerMeter
for x in self.arrows: for x in self.arrows:
if x: if x:
x.removeNode() x.removeNode()
@ -197,10 +208,12 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.ripples.stop() self.ripples.stop()
self.ripples.detachNode() self.ripples.detachNode()
del self.ripples del self.ripples
if self.suitRipples != None: if self.suitRipples != None:
self.suitRipples.stop() self.suitRipples.stop()
self.suitRipples.detachNode() self.suitRipples.detachNode()
del self.suitRipples del self.suitRipples
for x in self.avList: for x in self.avList:
del x del x
@ -208,6 +221,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
for x in self.tugRopes: for x in self.tugRopes:
if x != None: if x != None:
x.detachNode() x.detachNode()
del x del x
del self.tugRopes del self.tugRopes
@ -235,6 +249,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.suit: if self.suit:
self.suit.delete() self.suit.delete()
del self.suit del self.suit
del self.sides del self.sides
del self.buttons del self.buttons
del self.pullingDict del self.pullingDict
@ -245,26 +260,24 @@ class DistributedTugOfWarGame(DistributedMinigame):
del self.drinkPositions del self.drinkPositions
del self.offsetDict del self.offsetDict
del self.keyTTL del self.keyTTL
del self.rng
return
def onstage(self): def onstage(self):
self.notify.debug('onstage') self.notify.debug('onstage')
DistributedMinigame.onstage(self) DistributedMinigame.onstage(self)
self.lt = base.localAvatar self.lt = base.localAvatar
NametagGlobals.setGlobalNametagScale(1) NametagGlobals.setGlobalNametagScale(1)
self.arrowKeys = ArrowKeys.ArrowKeys() self.arrowKeys = ArrowKeys()
self.room.reparentTo(render) self.room.reparentTo(base.render)
self.room.setPosHpr(0.0, 18.39, -ToontownGlobals.FloorOffset, 0.0, 0.0, 0.0) self.room.setPosHpr(0.0, 18.39, -ToontownGlobals.FloorOffset, 0.0, 0.0, 0.0)
self.room.setScale(0.4) self.room.setScale(0.4)
self.sky.setZ(-5) self.sky.setZ(-5)
self.sky.reparentTo(render) self.sky.reparentTo(base.render)
self.dropShadow.setColor(0, 0, 0, 0.5) self.dropShadow.setColor(0, 0, 0, 0.5)
camera.reparentTo(render) base.camera.reparentTo(base.render)
camera.setPosHpr(-11.4427, 9.03559, 2.80094, -49.104, -0.89, 0) base.camera.setPosHpr(-11.4427, 9.03559, 2.80094, -49.104, -0.89, 0)
self.dropShadow.setBin('fixed', 0, 1) self.dropShadow.setBin('fixed', 0, 1)
self.splash.reparentTo(render) self.splash.reparentTo(base.render)
self.suitSplash.reparentTo(render) self.suitSplash.reparentTo(base.render)
base.playMusic(self.music, looping=1, volume=1) base.playMusic(self.music, looping=1, volume=1)
for x in range(len(self.arrows)): for x in range(len(self.arrows)):
self.arrows[x].show() self.arrows[x].show()
@ -280,20 +293,24 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.introTrack.finish() self.introTrack.finish()
del self.introTrack del self.introTrack
self.introTrack = None self.introTrack = None
for track in list(self.animTracks.values()): for track in list(self.animTracks.values()):
if track: if track:
track.finish() track.finish()
del track del track
self.animTracks = {} self.animTracks = {}
if self.showTrack: if self.showTrack:
self.showTrack.finish() self.showTrack.finish()
del self.showTrack del self.showTrack
self.showTrack = None self.showTrack = None
if self.setupTrack: if self.setupTrack:
self.setupTrack.finish() self.setupTrack.finish()
del self.setupTrack del self.setupTrack
self.setupTrack = None self.setupTrack = None
base.camLens.setFov(ToontownGlobals.DefaultCameraFov) base.camLens.setFov(ToontownGlobals.DefaultCameraFov)
base.camLens.setNearFar(ToontownGlobals.DefaultCameraNear, ToontownGlobals.DefaultCameraFar) base.camLens.setNearFar(ToontownGlobals.DefaultCameraNear, ToontownGlobals.DefaultCameraFar)
NametagGlobals.setGlobalNametagScale(1.0) NametagGlobals.setGlobalNametagScale(1.0)
@ -303,13 +320,14 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.arrowKeys.destroy() self.arrowKeys.destroy()
del self.arrowKeys del self.arrowKeys
self.arrowKeys = None self.arrowKeys = None
self.room.reparentTo(hidden)
self.sky.reparentTo(hidden) self.room.reparentTo(base.hidden)
self.splash.reparentTo(hidden) self.sky.reparentTo(base.hidden)
self.splash.reparentTo(base.hidden)
self.splash.stop() self.splash.stop()
self.suitSplash.reparentTo(hidden) self.suitSplash.reparentTo(base.hidden)
self.suitSplash.stop() self.suitSplash.stop()
self.ripples.reparentTo(hidden) self.ripples.reparentTo(base.hidden)
self.ripples.stop() self.ripples.stop()
self.hideControls() self.hideControls()
self.roundText.hide() self.roundText.hide()
@ -322,42 +340,36 @@ class DistributedTugOfWarGame(DistributedMinigame):
for x in self.tugRopes: for x in self.tugRopes:
if x != None: if x != None:
x.reparentTo(hidden) x.reparentTo(base.hidden)
if self.suit: if self.suit:
self.suit.reparentTo(hidden) self.suit.reparentTo(base.hidden)
for avId in self.avIdList: for avId in self.avIdList:
if avId in self.dropShadowDict: if avId in self.dropShadowDict:
self.dropShadowDict[avId].reparentTo(hidden) self.dropShadowDict[avId].reparentTo(base.hidden)
if self.suitId in self.dropShadowDict: if self.suitId in self.dropShadowDict:
self.dropShadowDict[self.suitId].reparentTo(hidden) self.dropShadowDict[self.suitId].reparentTo(base.hidden)
return
def initCamera(self): def initCamera(self):
birdseyePosHpr = [1.95461,
18.4891,
38.4646,
1.18185,
-87.5308,
0]
introPosHpr = [None] * 2 introPosHpr = [None] * 2
introPosHpr[0] = [VBase3(-11.4427, 9.03559, 2.80094), VBase3(-49.104, -0.732374, 0)] 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)] introPosHpr[1] = [VBase3(16.9291, 13.9302, 2.64282), VBase3(66.9685, -6.195, 0)]
gameCamHpr = VBase3(-1.13, 1.042, 0) gameCamHpr = VBase3(-1.13, 1.042, 0)
gameCamPos = VBase3(0, 1.0838, 2.745) gameCamPos = VBase3(0, 1.0838, 2.745)
camera.reparentTo(render) base.camera.reparentTo(base.render)
camera.setPosHpr(introPosHpr[self.sides[self.localAvId]][0], introPosHpr[self.sides[self.localAvId]][1]) base.camera.setPosHpr(introPosHpr[self.sides[self.localAvId]][0], introPosHpr[self.sides[self.localAvId]][1])
lerpDur = 8 lerpDur = 8
self.introTrack = LerpPosHprInterval(camera, lerpDur, pos=gameCamPos, hpr=gameCamHpr, blendType='easeInOut', name=self.uniqueName('introLerpCameraPos')) self.introTrack = LerpPosHprInterval(base.camera, lerpDur, pos=gameCamPos, hpr=gameCamHpr, blendType='easeInOut', name=self.uniqueName('introLerpCameraPos'))
self.introTrack.start() self.introTrack.start()
base.camLens.setFov(60 + 2 * self.numPlayers) base.camLens.setFov(60 + 2 * self.numPlayers)
base.camLens.setFar(450.0) base.camLens.setFar(450.0)
return
def sendGameType(self, index, suit): def sendGameType(self, index, suit):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
self.gameType = index self.gameType = index
self.suitLevel = suit self.suitLevel = suit
if suit == 1: if suit == 1:
@ -372,9 +384,11 @@ class DistributedTugOfWarGame(DistributedMinigame):
def setGameReady(self): def setGameReady(self):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
self.notify.debug('setGameReady') self.notify.debug('setGameReady')
if DistributedMinigame.setGameReady(self): if DistributedMinigame.setGameReady(self):
return return
self.initToons() self.initToons()
self.createSuits() self.createSuits()
self.calculatePositions() self.calculatePositions()
@ -389,7 +403,6 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.showTrack = None self.showTrack = None
self.setupTrack = None self.setupTrack = None
self.__initGameVars() self.__initGameVars()
return
def hideControls(self): def hideControls(self):
for x in range(len(self.arrows)): for x in range(len(self.arrows)):
@ -397,40 +410,39 @@ class DistributedTugOfWarGame(DistributedMinigame):
for rope in self.tugRopes: for rope in self.tugRopes:
if rope != None: if rope != None:
rope.reparentTo(hidden) rope.reparentTo(base.hidden)
for tex in self.ropeTex: for tex in self.ropeTex:
if tex != None: if tex != None:
for texi in tex: for texi in tex:
if texi: if texi:
texi.reparentTo(hidden) texi.reparentTo(base.hidden)
if self.powerMeter != None: if self.powerMeter != None:
self.powerMeter.unbind(DGG.B1PRESS) self.powerMeter.unbind(DGG.B1PRESS)
self.powerMeter.unbind(DGG.B1RELEASE) self.powerMeter.unbind(DGG.B1RELEASE)
self.powerMeter.hide() self.powerMeter.hide()
return
def setUpRopes(self, notTaut): def setUpRopes(self, notTaut):
if self.numPlayers == 1: if self.numPlayers == 1:
suitRightHand = self.suit.getRightHand() suitRightHand = self.suit.getRightHand()
toonRightHand = self.rightHandDict[self.avIdList[0]] toonRightHand = self.rightHandDict[self.avIdList[0]]
if notTaut: if notTaut:
self.tugRopes[0].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, self.tugRopes[0].setup(3, ((toonRightHand, (0, 0, 0)), (base.render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0,
0, 0,
0, 0,
1, 1,
1, 1,
1]) 1])
else: 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, self.tugRopes[0].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0,
0, 0,
0, 0,
1, 1,
1, 1,
1]) 1])
self.tugRopes[0].reparentTo(render)
self.tugRopes[0].reparentTo(base.render)
elif self.numPlayers == 2: elif self.numPlayers == 2:
if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: 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, 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,
@ -442,25 +454,25 @@ class DistributedTugOfWarGame(DistributedMinigame):
suitRightHand = self.suit.getRightHand() suitRightHand = self.suit.getRightHand()
toonRightHand = self.rightHandDict[self.avIdList[1]] toonRightHand = self.rightHandDict[self.avIdList[1]]
if notTaut: if notTaut:
self.tugRopes[1].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, self.tugRopes[1].setup(3, ((toonRightHand, (0, 0, 0)), (base.render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0,
0, 0,
0, 0,
1, 1,
1, 1,
1]) 1])
else: 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, self.tugRopes[1].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0,
0, 0,
0, 0,
1, 1,
1, 1,
1]) 1])
self.tugRopes[0].reparentTo(render)
self.tugRopes[1].reparentTo(render) self.tugRopes[0].reparentTo(base.render)
self.tugRopes[1].reparentTo(base.render)
else: else:
if notTaut: 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, self.tugRopes[0].setup(3, ((self.rightHandDict[self.avIdList[0]], (0, 0, 0)), (base.render, (0, 18, -1)), (self.rightHandDict[self.avIdList[1]], (0, 0, 0))), [0,
0, 0,
0, 0,
1, 1,
@ -473,7 +485,8 @@ class DistributedTugOfWarGame(DistributedMinigame):
1, 1,
1, 1,
1]) 1])
self.tugRopes[0].reparentTo(render)
self.tugRopes[0].reparentTo(base.render)
elif self.numPlayers == 3: elif self.numPlayers == 3:
if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: 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, 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,
@ -491,26 +504,26 @@ class DistributedTugOfWarGame(DistributedMinigame):
suitRightHand = self.suit.getRightHand() suitRightHand = self.suit.getRightHand()
toonRightHand = self.rightHandDict[self.avIdList[2]] toonRightHand = self.rightHandDict[self.avIdList[2]]
if notTaut: if notTaut:
self.tugRopes[2].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, self.tugRopes[2].setup(3, ((toonRightHand, (0, 0, 0)), (base.render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0,
0, 0,
0, 0,
1, 1,
1, 1,
1]) 1])
else: 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, self.tugRopes[2].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0,
0, 0,
0, 0,
1, 1,
1, 1,
1]) 1])
self.tugRopes[0].reparentTo(render)
self.tugRopes[1].reparentTo(render) self.tugRopes[0].reparentTo(base.render)
self.tugRopes[2].reparentTo(render) self.tugRopes[1].reparentTo(base.render)
self.tugRopes[2].reparentTo(base.render)
else: else:
if notTaut: 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, self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (base.render, (0, 18, -1)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0,
0, 0,
0, 0,
1, 1,
@ -523,14 +536,15 @@ class DistributedTugOfWarGame(DistributedMinigame):
1, 1,
1, 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, 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,
0, 0,
1, 1,
1, 1,
1]) 1])
self.tugRopes[0].reparentTo(render) self.tugRopes[0].reparentTo(base.render)
self.tugRopes[1].reparentTo(render) self.tugRopes[1].reparentTo(base.render)
elif self.numPlayers == 4: elif self.numPlayers == 4:
if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: 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, 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,
@ -554,24 +568,24 @@ class DistributedTugOfWarGame(DistributedMinigame):
suitRightHand = self.suit.getRightHand() suitRightHand = self.suit.getRightHand()
toonRightHand = self.rightHandDict[self.avIdList[3]] toonRightHand = self.rightHandDict[self.avIdList[3]]
if notTaut: if notTaut:
self.tugRopes[3].setup(3, ((toonRightHand, (0, 0, 0)), (render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0, self.tugRopes[3].setup(3, ((toonRightHand, (0, 0, 0)), (base.render, (0, 18, -1)), (suitRightHand, (0, 0, 0))), [0,
0, 0,
0, 0,
1, 1,
1, 1,
1]) 1])
else: 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, self.tugRopes[3].setup(3, ((toonRightHand, (0, 0, 0)), (toonRightHand, (0, 0, 0)), (suitRightHand, (0, 0, 0))), [0,
0, 0,
0, 0,
1, 1,
1, 1,
1]) 1])
self.tugRopes[0].reparentTo(render)
self.tugRopes[1].reparentTo(render) self.tugRopes[0].reparentTo(base.render)
self.tugRopes[2].reparentTo(render) self.tugRopes[1].reparentTo(base.render)
self.tugRopes[3].reparentTo(render) self.tugRopes[2].reparentTo(base.render)
self.tugRopes[3].reparentTo(base.render)
else: 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, 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,
@ -586,7 +600,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
1, 1,
1]) 1])
if notTaut: 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, self.tugRopes[1].setup(3, ((self.rightHandDict[self.avIdList[1]], (0, 0, 0)), (base.render, (0, 18, -1)), (self.rightHandDict[self.avIdList[2]], (0, 0, 0))), [0,
0, 0,
0, 0,
1, 1,
@ -599,15 +613,16 @@ class DistributedTugOfWarGame(DistributedMinigame):
1, 1,
1, 1,
1]) 1])
self.tugRopes[0].reparentTo(render)
self.tugRopes[1].reparentTo(render) self.tugRopes[0].reparentTo(base.render)
self.tugRopes[2].reparentTo(render) self.tugRopes[1].reparentTo(base.render)
self.tugRopes[2].reparentTo(base.render)
def initToons(self): def initToons(self):
for avId in self.avIdList: for avId in self.avIdList:
toon = self.getAvatar(avId) toon = self.getAvatar(avId)
if toon: if toon:
toon.reparentTo(render) toon.reparentTo(base.render)
toon.useLOD(1000) toon.useLOD(1000)
toon.startBlink() toon.startBlink()
toon.startLookAround() toon.startLookAround()
@ -618,7 +633,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.rightHandDict[avId] = toon.getRightHands()[0] self.rightHandDict[avId] = toon.getRightHands()[0]
toon.loop('neutral') toon.loop('neutral')
toon.dropShadow.hide() toon.dropShadow.hide()
self.dropShadowDict[avId] = self.dropShadow.copyTo(hidden) self.dropShadowDict[avId] = self.dropShadow.copyTo(base.hidden)
self.dropShadowDict[avId].reparentTo(toon) self.dropShadowDict[avId].reparentTo(toon)
self.dropShadowDict[avId].setScale(0.35) self.dropShadowDict[avId].setScale(0.35)
@ -696,6 +711,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.hprDict[self.avIdList[1]] = hprPositions[0] self.hprDict[self.avIdList[1]] = hprPositions[0]
self.hprDict[self.avIdList[2]] = hprPositions[1] self.hprDict[self.avIdList[2]] = hprPositions[1]
self.hprDict[self.avIdList[3]] = hprPositions[1] self.hprDict[self.avIdList[3]] = hprPositions[1]
for x in self.avIdList: for x in self.avIdList:
self.offsetDict[x] = 0 self.offsetDict[x] = 0
if self.posDict[x][0] < 0: if self.posDict[x][0] < 0:
@ -741,9 +757,11 @@ class DistributedTugOfWarGame(DistributedMinigame):
def setGameStart(self, timestamp): def setGameStart(self, timestamp):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
self.notify.debug('setGameStart') self.notify.debug('setGameStart')
if not self.__playing(): if not self.__playing():
return return
DistributedMinigame.setGameStart(self, timestamp) DistributedMinigame.setGameStart(self, timestamp)
self.gameFSM.request('waitForGoSignal') self.gameFSM.request('waitForGoSignal')
@ -751,7 +769,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
pass pass
def makeToonLookatCamera(self, toon): def makeToonLookatCamera(self, toon):
toon.headsUp(camera) toon.headsUp(base.camera)
def setText(self, t, newtext): def setText(self, t, newtext):
t['text'] = newtext t['text'] = newtext
@ -788,6 +806,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.notify.debug('exitTug') self.notify.debug('exitTug')
if self.suit: if self.suit:
self.suit.loop('neutral') self.suit.loop('neutral')
self.timer.stop() self.timer.stop()
self.timer.hide() self.timer.hide()
taskMgr.remove(self.taskName('tug-timeout')) taskMgr.remove(self.taskName('tug-timeout'))
@ -828,7 +847,8 @@ class DistributedTugOfWarGame(DistributedMinigame):
def __updateKeyPressRateTask(self, task): def __updateKeyPressRateTask(self, task):
if self.gameFSM.getCurrentState().getName() != 'tug': if self.gameFSM.getCurrentState().getName() != 'tug':
return Task.done return task.done
for i in range(len(self.keyTTL)): for i in range(len(self.keyTTL)):
self.keyTTL[i] -= 0.1 self.keyTTL[i] -= 0.1
@ -844,18 +864,20 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.rateMatchAward += 0.3 self.rateMatchAward += 0.3
else: else:
self.rateMatchAward = 0 self.rateMatchAward = 0
self.__spawnUpdateKeyPressRateTask() self.__spawnUpdateKeyPressRateTask()
return Task.done return task.done
def __updateTimerTask(self, task): def __updateTimerTask(self, task):
if self.gameFSM.getCurrentState().getName() != 'tug': if self.gameFSM.getCurrentState().getName() != 'tug':
return Task.done return task.done
self.currentForce = self.computeForce(self.keyRate) self.currentForce = self.computeForce(self.keyRate)
self.sendUpdate('reportCurrentKeyRate', [self.keyRate, self.currentForce]) self.sendUpdate('reportCurrentKeyRate', [self.keyRate, self.currentForce])
self.setSpeedGauge() self.setSpeedGauge()
self.setAnimState(self.localAvId, self.keyRate) self.setAnimState(self.localAvId, self.keyRate)
self.__spawnUpdateTimerTask() self.__spawnUpdateTimerTask()
return Task.done return task.done
def __spawnUpdateTimerTask(self): def __spawnUpdateTimerTask(self):
taskMgr.remove(self.taskName(self.UPDATE_TIMER_TASK)) taskMgr.remove(self.taskName(self.UPDATE_TIMER_TASK))
@ -881,10 +903,12 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.nextRateIndex < len(self.targetRateList): if self.nextRateIndex < len(self.targetRateList):
if self.nextRateIndex == len(self.targetRateList) - 1: if self.nextRateIndex == len(self.targetRateList) - 1:
self.allOutMode = 1 self.allOutMode = 1
self.idealRate = self.targetRateList[self.nextRateIndex][1] self.idealRate = self.targetRateList[self.nextRateIndex][1]
self.idealForce = self.advantage * (4 + 0.4 * self.idealRate) self.idealForce = self.advantage * (4 + 0.4 * self.idealRate)
taskMgr.doMethodLater(self.targetRateList[self.nextRateIndex][0], self.__updateIdealRateTask, self.taskName('targetRateTimer')) taskMgr.doMethodLater(self.targetRateList[self.nextRateIndex][0], self.__updateIdealRateTask, self.taskName('targetRateTimer'))
return Task.done
return task.done
def __killUpdateIdealRateTask(self): def __killUpdateIdealRateTask(self):
taskMgr.remove(self.taskName('targetRateTimer')) taskMgr.remove(self.taskName('targetRateTimer'))
@ -892,14 +916,14 @@ class DistributedTugOfWarGame(DistributedMinigame):
def sendGoSignal(self, index): def sendGoSignal(self, index):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
self.notify.debug('sendGoSignal') self.notify.debug('sendGoSignal')
self.buttons = index self.buttons = index
self.setupTrack = None self.setupTrack = None
self.showTrack = None self.showTrack = None
def startTimer(self = self): def startTimer(self = self):
self.currentStartTime = int(globalClock.getFrameTime() * 1000) self.currentStartTime = int(base.clock.getFrameTime() * 1000)
time = 10
self.timer.show() self.timer.show()
self.timer.setTime(TugOfWarGameGlobals.GAME_DURATION) self.timer.setTime(TugOfWarGameGlobals.GAME_DURATION)
self.timer.countdown(TugOfWarGameGlobals.GAME_DURATION, self.__gameTimerExpired) self.timer.countdown(TugOfWarGameGlobals.GAME_DURATION, self.__gameTimerExpired)
@ -926,13 +950,14 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.introTrack != None: if self.introTrack != None:
self.introTrack.finish() self.introTrack.finish()
self.introTrack = None 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 = 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() self.setupTrack.start()
return
def sendStopSignal(self, winners, losers, tieers): def sendStopSignal(self, winners, losers, tieers):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
self.notify.debug('sendStopSignal') self.notify.debug('sendStopSignal')
self.gameFSM.request('gameDone') self.gameFSM.request('gameDone')
self.hideControls() self.hideControls()
@ -941,6 +966,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
suitSlipTime = 0 suitSlipTime = 0
if self.gameFSM.getCurrentState().getName() == 'cleanup' or not self.randomNumGen: if self.gameFSM.getCurrentState().getName() == 'cleanup' or not self.randomNumGen:
return return
if self.suit: if self.suit:
if self.suitId in winners: if self.suitId in winners:
newPos = VBase3(2.65, 18, 0.1) newPos = VBase3(2.65, 18, 0.1)
@ -959,6 +985,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
destHpr = startHpr + VBase3(0, 0, -30) 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)))) 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'))) 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: for avId in self.avIdList:
toon = self.getAvatar(avId) toon = self.getAvatar(avId)
toon.loop('neutral') toon.loop('neutral')
@ -978,6 +1005,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
else: else:
exitSeq.append(Func(self.setText, self.roundText, TTLocalizer.TugOfWarGameTie)) exitSeq.append(Func(self.setText, self.roundText, TTLocalizer.TugOfWarGameTie))
exitSeq.append(Wait(2.5)) exitSeq.append(Wait(2.5))
exitSeq.append(Func(self.gameOver)) exitSeq.append(Func(self.gameOver))
self.showTrack = Parallel(reactSeq, exitSeq) self.showTrack = Parallel(reactSeq, exitSeq)
for x in list(self.animTracks.values()): for x in list(self.animTracks.values()):
@ -988,27 +1016,31 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.arrowKeys: if self.arrowKeys:
self.arrowKeys.setPressHandlers(self.arrowKeys.NULL_HANDLERS) self.arrowKeys.setPressHandlers(self.arrowKeys.NULL_HANDLERS)
self.arrowKeys.setReleaseHandlers(self.arrowKeys.NULL_HANDLERS) self.arrowKeys.setReleaseHandlers(self.arrowKeys.NULL_HANDLERS)
return
def remoteKeyRateUpdate(self, avId, keyRate): def remoteKeyRateUpdate(self, avId, keyRate):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
if avId != self.localAvId: if avId != self.localAvId:
self.setAnimState(avId, keyRate) self.setAnimState(avId, keyRate)
def sendSuitPosition(self, suitOffset): def sendSuitPosition(self, suitOffset):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
if self.gameFSM.getCurrentState().getName() != 'tug': if self.gameFSM.getCurrentState().getName() != 'tug':
return return
self.suitOffset = suitOffset self.suitOffset = suitOffset
self.moveSuits() self.moveSuits()
def sendCurrentPosition(self, avIdList, offsetList): def sendCurrentPosition(self, avIdList, offsetList):
if not self.hasLocalToon: if not self.hasLocalToon:
return return
if self.gameFSM.getCurrentState().getName() != 'tug': if self.gameFSM.getCurrentState().getName() != 'tug':
return return
for i in range(len(avIdList)): for i in range(len(avIdList)):
self.offsetDict[avIdList[i]] = offsetList[i] self.offsetDict[avIdList[i]] = offsetList[i]
@ -1017,20 +1049,20 @@ class DistributedTugOfWarGame(DistributedMinigame):
def createSuits(self): def createSuits(self):
if self.gameType == TugOfWarGameGlobals.TOON_VS_COG: if self.gameType == TugOfWarGameGlobals.TOON_VS_COG:
self.suit = Suit.Suit() self.suit = Suit()
self.origSuitPosHpr = [VBase3(6.0, 18, 0.1), VBase3(120, 0, 0)] self.origSuitPosHpr = [VBase3(6.0, 18, 0.1), VBase3(120, 0, 0)]
self.suitOffset = 0 self.suitOffset = 0
d = SuitDNA.SuitDNA() d = SuitDNA()
d.newSuit(self.suitType) d.newSuit(self.suitType)
self.suit.setDNA(d) self.suit.setDNA(d)
self.suit.reparentTo(render) self.suit.reparentTo(base.render)
self.suit.setPos(self.origSuitPosHpr[0]) self.suit.setPos(self.origSuitPosHpr[0])
self.suit.setHpr(self.origSuitPosHpr[1]) self.suit.setHpr(self.origSuitPosHpr[1])
for anim in self.suitAnimNames: for anim in self.suitAnimNames:
self.suit.pose(anim, 0) self.suit.pose(anim, 0)
self.suit.pose('tug-o-war', 0) self.suit.pose('tug-o-war', 0)
self.dropShadowDict[self.suitId] = self.dropShadow.copyTo(hidden) self.dropShadowDict[self.suitId] = self.dropShadow.copyTo(base.hidden)
self.dropShadowDict[self.suitId].reparentTo(self.suit) self.dropShadowDict[self.suitId].reparentTo(self.suit)
self.dropShadowDict[self.suitId].setScale(0.45) self.dropShadowDict[self.suitId].setScale(0.45)
@ -1040,11 +1072,13 @@ class DistributedTugOfWarGame(DistributedMinigame):
toon = self.getAvatar(self.avList[0][0]) toon = self.getAvatar(self.avList[0][0])
if self.avList[0][0] == self.localAvId: if self.avList[0][0] == self.localAvId:
self.advantage = 2.0 self.advantage = 2.0
toon.applyCheesyEffect(ToontownGlobals.CEBigHead) toon.applyCheesyEffect(ToontownGlobals.CEBigHead)
elif len(self.avList[1]) == 1: elif len(self.avList[1]) == 1:
toon = self.getAvatar(self.avList[1][0]) toon = self.getAvatar(self.avList[1][0])
if self.avList[1][0] == self.localAvId: if self.avList[1][0] == self.localAvId:
self.advantage = 2.0 self.advantage = 2.0
toon.applyCheesyEffect(ToontownGlobals.CEBigHead) toon.applyCheesyEffect(ToontownGlobals.CEBigHead)
def setSpeedGauge(self): def setSpeedGauge(self):
@ -1052,12 +1086,14 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.powerMeter.setTarget(self.idealRate) self.powerMeter.setTarget(self.idealRate)
if not self.allOutMode: if not self.allOutMode:
self.powerMeter.updateTooSlowTooFast() self.powerMeter.updateTooSlowTooFast()
if not self.allOutMode: if not self.allOutMode:
index = float(self.currentForce) / self.idealForce index = float(self.currentForce) / self.idealForce
bonus = 0.0 bonus = 0.0
if index > 1: if index > 1:
bonus = max(1, index - 1) bonus = max(1, index - 1)
index = 1 index = 1
color = (0, color = (0,
0.75 * index + 0.25 * bonus, 0.75 * index + 0.25 * bonus,
0.75 * (1 - index), 0.75 * (1 - index),
@ -1069,10 +1105,12 @@ class DistributedTugOfWarGame(DistributedMinigame):
def setAnimState(self, avId, keyRate): def setAnimState(self, avId, keyRate):
if self.gameFSM.getCurrentState().getName() != 'tug': if self.gameFSM.getCurrentState().getName() != 'tug':
return return
toon = self.getAvatar(avId) toon = self.getAvatar(avId)
if keyRate > 0 and self.pullingDict[avId] == 0: if keyRate > 0 and self.pullingDict[avId] == 0:
toon.loop('tug-o-war') toon.loop('tug-o-war')
self.pullingDict[avId] = 1 self.pullingDict[avId] = 1
if keyRate <= 0 and self.pullingDict[avId] == 1: if keyRate <= 0 and self.pullingDict[avId] == 1:
toon.pose('tug-o-war', 3) toon.pose('tug-o-war', 3)
toon.startLookAround() toon.startLookAround()
@ -1081,6 +1119,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
def moveSuits(self): def moveSuits(self):
if self.gameType != TugOfWarGameGlobals.TOON_VS_COG: if self.gameType != TugOfWarGameGlobals.TOON_VS_COG:
return return
origPos = self.origSuitPosHpr[0] origPos = self.origSuitPosHpr[0]
curPos = self.suit.getPos() curPos = self.suit.getPos()
newPos = VBase3(origPos[0] + self.suitOffset, curPos[1], curPos[2]) newPos = VBase3(origPos[0] + self.suitOffset, curPos[1], curPos[2])
@ -1088,10 +1127,10 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.animTracks[self.suitId].isPlaying(): if self.animTracks[self.suitId].isPlaying():
self.animTracks[self.suitId].finish() self.animTracks[self.suitId].finish()
self.checkIfFallen() self.checkIfFallen()
if self.suitId not in self.fallenList: 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] = Sequence(LerpPosInterval(self.suit, duration=TugOfWarGameGlobals.SEND_UPDATE, pos=newPos), Func(self.checkIfFallen))
self.animTracks[self.suitId].start() self.animTracks[self.suitId].start()
return
def moveToons(self): def moveToons(self):
for avId in self.avIdList: for avId in self.avIdList:
@ -1105,12 +1144,11 @@ class DistributedTugOfWarGame(DistributedMinigame):
if self.animTracks[avId].isPlaying(): if self.animTracks[avId].isPlaying():
self.animTracks[avId].finish() self.animTracks[avId].finish()
self.checkIfFallen(avId) self.checkIfFallen(avId)
if avId not in self.fallenList: 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] = Sequence(LerpPosInterval(toon, duration=TugOfWarGameGlobals.SEND_UPDATE, pos=newPos), Func(self.checkIfFallen, avId))
self.animTracks[avId].start() self.animTracks[avId].start()
return
def checkIfFallen(self, avId = None): def checkIfFallen(self, avId = None):
if avId == None: if avId == None:
if self.suitId not in self.fallenList: if self.suitId not in self.fallenList:
@ -1132,7 +1170,6 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.throwInWater(avId) self.throwInWater(avId)
self.sendUpdate('reportEndOfContest', [losingSide]) self.sendUpdate('reportEndOfContest', [losingSide])
return
def throwInWater(self, avId = None): def throwInWater(self, avId = None):
if avId == None: if avId == None:
@ -1140,7 +1177,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
waterPos = self.drinkPositions.pop() waterPos = self.drinkPositions.pop()
newPos = VBase3(waterPos[0], waterPos[1], waterPos[2] - self.suit.getHeight() / 1.5) newPos = VBase3(waterPos[0], waterPos[1], waterPos[2] - self.suit.getHeight() / 1.5)
self.suit.loop('neutral') self.suit.loop('neutral')
self.dropShadowDict[self.suitId].reparentTo(hidden) self.dropShadowDict[self.suitId].reparentTo(base.hidden)
loser = self.suit loser = self.suit
animId = self.suitId animId = self.suitId
else: else:
@ -1149,19 +1186,20 @@ class DistributedTugOfWarGame(DistributedMinigame):
waterPos = self.drinkPositions.pop() waterPos = self.drinkPositions.pop()
newPos = VBase3(waterPos[0], waterPos[1], waterPos[2] - toon.getHeight()) newPos = VBase3(waterPos[0], waterPos[1], waterPos[2] - toon.getHeight())
toon.loop('neutral') toon.loop('neutral')
self.dropShadowDict[avId].reparentTo(hidden) self.dropShadowDict[avId].reparentTo(base.hidden)
loser = toon loser = toon
animId = avId animId = avId
if self.animTracks[animId] != None: if self.animTracks[animId] != None:
if self.animTracks[animId].isPlaying(): if self.animTracks[animId].isPlaying():
self.animTracks[animId].finish() self.animTracks[animId].finish()
self.splash.setPos(newPos[0], newPos[1], -1.8) self.splash.setPos(newPos[0], newPos[1], -1.8)
self.splash.setScale(2.5, 2.5, 1) self.splash.setScale(2.5, 2.5, 1)
self.ripples.setPos(newPos[0], newPos[1], -1.7) self.ripples.setPos(newPos[0], newPos[1], -1.7)
self.ripples.setScale(1, 1, 1) 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] = 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() self.animTracks[animId].start()
return
def computeForce(self, keyRate): def computeForce(self, keyRate):
F = 0 F = 0
@ -1170,6 +1208,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
else: else:
stdDev = 0.25 * self.idealRate 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))) 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 return F
def initRopes(self): def initRopes(self):
@ -1177,8 +1216,9 @@ class DistributedTugOfWarGame(DistributedMinigame):
numRopes = self.numPlayers numRopes = self.numPlayers
else: else:
numRopes = self.numPlayers - 1 numRopes = self.numPlayers - 1
for x in range(0, numRopes): for x in range(0, numRopes):
rope = Rope.Rope(self.uniqueName('TugRope' + str(x))) rope = Rope(self.uniqueName('TugRope' + str(x)))
if rope.showRope: if rope.showRope:
rope.ropeNode.setRenderMode(RopeNode.RMBillboard) rope.ropeNode.setRenderMode(RopeNode.RMBillboard)
rope.ropeNode.setThickness(0.2) rope.ropeNode.setThickness(0.2)
@ -1187,6 +1227,7 @@ class DistributedTugOfWarGame(DistributedMinigame):
rope.ropeNode.setUvDirection(1) rope.ropeNode.setUvDirection(1)
rope.setTransparency(1) rope.setTransparency(1)
rope.setColor(0.89, 0.89, 0.6, 1) rope.setColor(0.89, 0.89, 0.6, 1)
self.tugRopes.append(rope) self.tugRopes.append(rope)
self.setUpRopes(1) self.setUpRopes(1)
@ -1203,18 +1244,18 @@ class DistributedTugOfWarGame(DistributedMinigame):
for j in range(len(self.ropePts[i])): for j in range(len(self.ropePts[i])):
self.ropeTex[i][j].setPos(self.ropePts[i][j]) self.ropeTex[i][j].setPos(self.ropePts[i][j])
return Task.cont return task.cont
def __killUpdateRopeTask(self): def __killUpdateRopeTask(self):
taskMgr.remove(self.taskName(self.UPDATE_ROPE_TASK)) taskMgr.remove(self.taskName(self.UPDATE_ROPE_TASK))
def tugTimeoutTask(self, task): def tugTimeoutTask(self, task):
self.gameOver() self.gameOver()
return Task.done return task.done
def waitForGoTimeoutTask(self, task): def waitForGoTimeoutTask(self, task):
self.gameOver() self.gameOver()
return Task.done return task.done
def __spawnMouseSpeedTask(self): def __spawnMouseSpeedTask(self):
taskMgr.remove(self.taskName('mouseSpeed')) taskMgr.remove(self.taskName('mouseSpeed'))
@ -1227,7 +1268,6 @@ class DistributedTugOfWarGame(DistributedMinigame):
dx = 0.1 dx = 0.1
if self.mouseMode: if self.mouseMode:
mx = base.mouseWatcherNode.getMouseX() mx = base.mouseWatcherNode.getMouseX()
my = base.mouseWatcherNode.getMouseY()
if self.mouseSide == 0: if self.mouseSide == 0:
if mx > dx: if mx > dx:
self.mouseSide = 1 self.mouseSide = 1
@ -1242,4 +1282,5 @@ class DistributedTugOfWarGame(DistributedMinigame):
self.__pressHandler(1) self.__pressHandler(1)
elif mx < dx: elif mx < dx:
self.__releaseHandler(0) self.__releaseHandler(0)
return Task.cont
return task.cont