Feature: Implemented MML Piano Marry-Go-Round

This commit is contained in:
Loudrob 2015-03-16 09:41:50 -04:00
parent d252a5cd03
commit 8e070a2231
6 changed files with 140 additions and 58 deletions

View file

@ -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;

View file

@ -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

View file

@ -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)

View file

@ -1,3 +1,4 @@
import random
from pandac.PandaModules import *
from direct.task.Task import Task
from direct.distributed.ClockDelta import *
@ -9,6 +10,7 @@ ChangeDirectionDebounce = 1.0
ChangeDirectionTime = 1.0
class DistributedMMPiano(DistributedObject.DistributedObject):
whitePartNodeName = 'midkey_floor_1'
def __init__(self, cr):
DistributedObject.DistributedObject.__init__(self, cr)
@ -16,24 +18,36 @@ class DistributedMMPiano(DistributedObject.DistributedObject):
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:
if self.degreesPerSecond == 0:
return Task.cont
elapsed = globalClock.getRealTime() - self.spinStartTime
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)
heading = ((self.degreesPerSecond * elapsed) + offset) % 360
self.piano.setH(heading)
return Task.cont
def disable(self):
if hasattr(self, 'piano'):
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')
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
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.')

View file

@ -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]
def setSpeed(self, todo0, todo1, todo2):
pass
self.updateSpeed(rpm, -(self.direction))
self.__slowDownLater()
self.d_playChangeDirection(self.air.getAvatarIdFromSender())
def playSpeedUp(self, todo0):
pass
def d_setSpeed(self, rpm, offset, startTime):
self.sendUpdate('setSpeed', [rpm, offset, globalClockDelta.localToNetworkTime(startTime)])
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

View file

@ -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)