From 8e070a2231bcf3258a44d35b4a7bc04ae16d7c76 Mon Sep 17 00:00:00 2001 From: Loudrob Date: Mon, 16 Mar 2015 09:41:50 -0400 Subject: [PATCH] Feature: Implemented MML Piano Marry-Go-Round --- astron/dclass/toon.dc | 1 + otp/distributed/DCClassImports.py | 2 +- toontown/hood/MMHoodAI.py | 6 ++ toontown/safezone/DistributedMMPiano.py | 87 ++++++++++++----------- toontown/safezone/DistributedMMPianoAI.py | 80 +++++++++++++++++---- toontown/safezone/MMPlayground.py | 22 ++++++ 6 files changed, 140 insertions(+), 58 deletions(-) diff --git a/astron/dclass/toon.dc b/astron/dclass/toon.dc index dd56cea7..29f996de 100644 --- a/astron/dclass/toon.dc +++ b/astron/dclass/toon.dc @@ -953,6 +953,7 @@ dclass DistributedButterfly : DistributedObject { dclass DistributedMMPiano : DistributedObject { requestSpeedUp() airecv clsend; + requestSlowDown() airecv clsend; requestChangeDirection() airecv clsend; setSpeed(int16/1000, uint16/100, int16) broadcast ram; playSpeedUp(uint32) broadcast; diff --git a/otp/distributed/DCClassImports.py b/otp/distributed/DCClassImports.py index 5e0e26e6..e20a8c6f 100644 --- a/otp/distributed/DCClassImports.py +++ b/otp/distributed/DCClassImports.py @@ -2,7 +2,7 @@ from pandac.PandaModules import * -hashVal = 1610389195 +hashVal = 177192120 from toontown.coghq import DistributedCashbotBossSafe, DistributedCashbotBossCrane, DistributedBattleFactory, DistributedCashbotBossTreasure, DistributedCogHQDoor, DistributedSellbotHQDoor, DistributedFactoryElevatorExt, DistributedMintElevatorExt, DistributedLawOfficeElevatorExt, DistributedLawOfficeElevatorInt, LobbyManager, DistributedMegaCorp, DistributedFactory, DistributedLawOffice, DistributedLawOfficeFloor, DistributedLift, DistributedDoorEntity, DistributedSwitch, DistributedButton, DistributedTrigger, DistributedCrushableEntity, DistributedCrusherEntity, DistributedStomper, DistributedStomperPair, DistributedLaserField, DistributedGolfGreenGame, DistributedSecurityCamera, DistributedMover, DistributedElevatorMarker, DistributedBarrelBase, DistributedGagBarrel, DistributedBeanBarrel, DistributedHealBarrel, DistributedGrid, ActiveCell, DirectionalCell, CrusherCell, DistributedCrate, DistributedSinkingPlatform, BattleBlocker, DistributedMint, DistributedMintRoom, DistributedMintBattle, DistributedStage, DistributedStageRoom, DistributedStageBattle, DistributedLawbotBossGavel, DistributedLawbotCannon, DistributedLawbotChair, DistributedCogKart, DistributedCountryClub, DistributedCountryClubRoom, DistributedMoleField, DistributedCountryClubBattle, DistributedMaze, DistributedFoodBelt, DistributedBanquetTable, DistributedGolfSpot diff --git a/toontown/hood/MMHoodAI.py b/toontown/hood/MMHoodAI.py index 71fb1226..53b8e6eb 100644 --- a/toontown/hood/MMHoodAI.py +++ b/toontown/hood/MMHoodAI.py @@ -1,10 +1,12 @@ from toontown.classicchars import DistributedMinnieAI from toontown.hood import HoodAI from toontown.safezone import DistributedTrolleyAI +from toontown.safezone import DistributedMMPianoAI from toontown.toonbase import ToontownGlobals from toontown.ai import DistributedTrickOrTreatTargetAI + class MMHoodAI(HoodAI.HoodAI): def __init__(self, air): HoodAI.HoodAI.__init__(self, air, @@ -12,6 +14,7 @@ class MMHoodAI(HoodAI.HoodAI): ToontownGlobals.MinniesMelodyland) self.trolley = None + self.piano = None self.classicChar = None self.startup() @@ -25,6 +28,9 @@ class MMHoodAI(HoodAI.HoodAI): if simbase.config.GetBool('want-minnie', True): self.createClassicChar() + self.piano = DistributedMMPianoAI.DistributedMMPianoAI(self.air) + self.piano.generateWithRequired(self.zoneId) + if simbase.air.wantHalloween: self.TrickOrTreatTargetManager = DistributedTrickOrTreatTargetAI.DistributedTrickOrTreatTargetAI(self.air) self.TrickOrTreatTargetManager.generateWithRequired(4835) diff --git a/toontown/safezone/DistributedMMPiano.py b/toontown/safezone/DistributedMMPiano.py index 81822ad6..a3e9522c 100644 --- a/toontown/safezone/DistributedMMPiano.py +++ b/toontown/safezone/DistributedMMPiano.py @@ -1,3 +1,4 @@ +import random from pandac.PandaModules import * from direct.task.Task import Task from direct.distributed.ClockDelta import * @@ -9,31 +10,44 @@ ChangeDirectionDebounce = 1.0 ChangeDirectionTime = 1.0 class DistributedMMPiano(DistributedObject.DistributedObject): - + whitePartNodeName = 'midkey_floor_1' + def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.spinStartTime = 0.0 self.rpm = 0.0 self.degreesPerSecond = self.rpm / 60.0 * 360.0 self.offset = 0.0 - self.oldOffset = 0.0 - self.lerpStart = 0.0 - self.lerpFinish = 1.0 self.speedUpSound = None self.changeDirectionSound = None self.lastChangeDirection = 0.0 - return def generate(self): - self.piano = base.cr.playGame.hood.loader.piano + DistributedObject.DistributedObject.generate(self) + taskMgr.doMethodLater(4, self.setupGeom, self.uniqueName('setup-geom')) + + def setupGeom(self, task): + geom = self.cr.playGame.getPlace().loader.geom + self.piano = geom.find('**/center_icon') + if self.piano.isEmpty(): + loader.notify.error('Piano not found') + return + + geom.find('**/center_icon').setPos(0,-20.1,0) + geom.find('**/midkey_floor').setPos(0,20.1,0) + geom.find('**/pond_floor').setPos(0,20.1,0) + geom.find('**/pond_floor').setScale(1.01,1.01,1) + geom.find('**/MMsz_water').setPos(0,20.0,0) + geom.find('**/midkey_floor').setScale(1.01,1.01,1) + geom.find('**/midkey_floor_1').setScale(1.01,1.01,1) base.cr.parentMgr.registerParent(ToontownGlobals.SPMinniesPiano, self.piano) - self.accept('enterlarge_round_keyboard_collisions', self.__handleOnFloor) - self.accept('exitlarge_round_keyboard_collisions', self.__handleOffFloor) - self.accept('entero7', self.__handleChangeDirectionButton) + self.accept('enter' + self.whitePartNodeName, self.__handleOnFloor) + self.accept('exit' + self.whitePartNodeName, self.__handleOffFloor) + self.accept('entermid_fishpond', self.__handleChangeDirectionButton) self.speedUpSound = base.loadSfx('phase_6/audio/sfx/SZ_MM_gliss.ogg') self.changeDirectionSound = base.loadSfx('phase_6/audio/sfx/SZ_MM_cymbal.ogg') self.__setupSpin() - DistributedObject.DistributedObject.generate(self) + return task.done def __setupSpin(self): taskMgr.add(self.__updateSpin, self.taskName('pianoSpinTask')) @@ -42,51 +56,32 @@ class DistributedMMPiano(DistributedObject.DistributedObject): taskMgr.remove(self.taskName('pianoSpinTask')) def __updateSpin(self, task): - now = globalClock.getFrameTime() - if now > self.lerpFinish: - offset = self.offset - elif now > self.lerpStart: - t = (now - self.lerpStart) / (self.lerpFinish - self.lerpStart) - offset = self.oldOffset + t * (self.offset - self.oldOffset) - else: - offset = self.oldOffset - heading = self.degreesPerSecond * (now - self.spinStartTime) + offset - self.piano.setHprScale(heading % 360.0, 0.0, 0.0, 1.0, 1.0, 1.0) + if self.degreesPerSecond == 0: + return Task.cont + + elapsed = globalClock.getRealTime() - self.spinStartTime + offset = self.offset + heading = ((self.degreesPerSecond * elapsed) + offset) % 360 + self.piano.setH(heading) return Task.cont def disable(self): - del self.piano - base.cr.parentMgr.unregisterParent(ToontownGlobals.SPMinniesPiano) - self.ignore('enterlarge_round_keyboard_collisions') - self.ignore('exitlarge_round_keyboard_collisions') - self.ignore('entero7') - self.ignore('entericon_center_collisions') + if hasattr(self, 'piano'): + del self.piano + base.cr.parentMgr.unregisterParent(ToontownGlobals.SPMinniesPiano) + self.ignoreAll() self.speedUpSound = None self.changeDirectionSound = None self.__stopSpin() DistributedObject.DistributedObject.disable(self) - return def setSpeed(self, rpm, offset, timestamp): timestamp = globalClockDelta.networkToLocalTime(timestamp) degreesPerSecond = rpm / 60.0 * 360.0 - now = globalClock.getFrameTime() - oldHeading = self.degreesPerSecond * (now - self.spinStartTime) + self.offset - oldHeading = oldHeading % 360.0 - oldOffset = oldHeading - degreesPerSecond * (now - timestamp) self.rpm = rpm self.degreesPerSecond = degreesPerSecond self.offset = offset self.spinStartTime = timestamp - while oldOffset - offset < -180.0: - oldOffset += 360.0 - - while oldOffset - offset > 180.0: - oldOffset -= 360.0 - - self.oldOffset = oldOffset - self.lerpStart = now - self.lerpFinish = timestamp + ChangeDirectionTime def playSpeedUp(self, avId): if avId != base.localAvatar.doId: @@ -103,6 +98,7 @@ class DistributedMMPiano(DistributedObject.DistributedObject): def __handleOffFloor(self, collEntry): self.cr.playGame.getPlace().activityFsm.request('off') + self.sendUpdate('requestSlowDown', []) def __handleSpeedUpButton(self, collEntry): self.sendUpdate('requestSpeedUp', []) @@ -111,7 +107,12 @@ class DistributedMMPiano(DistributedObject.DistributedObject): def __handleChangeDirectionButton(self, collEntry): now = globalClock.getFrameTime() if now - self.lastChangeDirection < ChangeDirectionDebounce: + loader.notify.debug('Rejecting change direction.') return - self.lastChangeDirection = now - self.sendUpdate('requestChangeDirection', []) - base.playSfx(self.changeDirectionSound) + shouldChange = random.randint(1,10) + if int(shouldChange) == 10: + self.lastChangeDirection = now + self.sendUpdate('requestChangeDirection', []) + base.playSfx(self.changeDirectionSound) + else: + loader.notify.debug('Rejecting change direction.') \ No newline at end of file diff --git a/toontown/safezone/DistributedMMPianoAI.py b/toontown/safezone/DistributedMMPianoAI.py index 6bec13d3..18930d31 100644 --- a/toontown/safezone/DistributedMMPianoAI.py +++ b/toontown/safezone/DistributedMMPianoAI.py @@ -1,21 +1,73 @@ -from direct.directnotify import DirectNotifyGlobal -from direct.distributed.DistributedObjectAI import DistributedObjectAI +from otp.ai.AIBase import * +from toontown.toonbase.ToontownGlobals import * +from direct.distributed.ClockDelta import * +from direct.distributed import DistributedObjectAI +from direct.task import Task +PianoSpeeds = [2, 4, 6, 8, 10, 12, 15, 20] +PianoMaxSpeed = PianoSpeeds[-1] +PianoSlowDownFactor = 0.7 +PianoSlowDownInterval = 6.0 +PianoSlowDownMinimum = 0.1 -class DistributedMMPianoAI(DistributedObjectAI): - notify = DirectNotifyGlobal.directNotify.newCategory("DistributedMMPianoAI") +class DistributedMMPianoAI(DistributedObjectAI.DistributedObjectAI): + + def __init__(self, air): + DistributedObjectAI.DistributedObjectAI.__init__(self, air) + self.spinStartTime = 0.0 + self.rpm = 0.0 + self.degreesPerSecond = (self.rpm / 60.0) * 360.0 + self.offset = 0.0 + self.direction = 1 def requestSpeedUp(self): - pass + if self.rpm < PianoMaxSpeed: + for speed in PianoSpeeds: + if speed > self.rpm: + break + + self.updateSpeed(speed, self.direction) + + self.d_playSpeedUp(self.air.getAvatarIdFromSender()) + self.__slowDownLater() def requestChangeDirection(self): - pass + rpm = self.rpm + if rpm == 0.0: + rpm = PianoSpeeds[0] + + self.updateSpeed(rpm, -(self.direction)) + self.__slowDownLater() + self.d_playChangeDirection(self.air.getAvatarIdFromSender()) + + def d_setSpeed(self, rpm, offset, startTime): + self.sendUpdate('setSpeed', [rpm, offset, globalClockDelta.localToNetworkTime(startTime)]) - def setSpeed(self, todo0, todo1, todo2): - pass - - def playSpeedUp(self, todo0): - pass - - def playChangeDirection(self, todo0): - pass + def d_playSpeedUp(self, avId): + self.sendUpdate('playSpeedUp', [avId]) + + def d_playChangeDirection(self, avId): + self.sendUpdate('playChangeDirection', [avId]) + + def updateSpeed(self, rpm, direction): + now = globalClock.getFrameTime() + heading = self.degreesPerSecond * (now - self.spinStartTime) + self.offset + self.rpm = rpm + self.direction = direction + self.degreesPerSecond = (rpm / 60.0) * 360.0 * direction + self.offset = heading % 360.0 + self.spinStartTime = now + self.d_setSpeed(self.rpm * self.direction, self.offset, self.spinStartTime) + + def __slowDownLater(self): + taskName = self.uniqueName('slowDown') + taskMgr.remove(taskName) + taskMgr.doMethodLater(PianoSlowDownInterval, self.__slowDown, taskName) + def __slowDown(self, task): + rpm = self.rpm * PianoSlowDownFactor + if rpm < PianoSlowDownMinimum: + self.updateSpeed(0.0, self.direction) + else: + self.updateSpeed(rpm, self.direction) + self.__slowDownLater() + return Task.done diff --git a/toontown/safezone/MMPlayground.py b/toontown/safezone/MMPlayground.py index 154bfa24..5dd4a805 100644 --- a/toontown/safezone/MMPlayground.py +++ b/toontown/safezone/MMPlayground.py @@ -1,8 +1,30 @@ from toontown.classicchars import CCharPaths +from direct.fsm import ClassicFSM, State +import random from toontown.safezone import Playground from toontown.toonbase import TTLocalizer +from toontown.toonbase import ToontownGlobals class MMPlayground(Playground.Playground): + def __init__(self, loader, parentFSM, doneEvent): + Playground.Playground.__init__(self, loader, parentFSM, doneEvent) + self.activityFsm = ClassicFSM.ClassicFSM('Activity', [State.State('off', self.enterOff, self.exitOff, ['OnPiano']), State.State('OnPiano', self.enterOnPiano, self.exitOnPiano, ['off'])], 'off', 'off') + self.activityFsm.enterInitialState() + def showPaths(self): self.showPathPoints(CCharPaths.getPaths(TTLocalizer.Minnie)) + + def enterOff(self): + return None + + def exitOff(self): + return None + + def enterOnPiano(self): + base.localAvatar.b_setParent(ToontownGlobals.SPMinniesPiano) + + def exitOnPiano(self): + base.localAvatar.b_setParent(ToontownGlobals.SPRender) + +