toontown-just-works/toontown/town/Street.py
2024-07-07 18:08:39 -05:00

361 lines
15 KiB
Python

from panda3d.core import *
from toontown.battle.BattleProps import *
from toontown.battle.BattleSounds import *
from toontown.distributed.ToontownMsgTypes import *
from direct.gui.DirectGui import cleanupDialog
from direct.directnotify import DirectNotifyGlobal
from toontown.hood import Place
from toontown.battle import BattlePlace
from direct.showbase import DirectObject
from direct.fsm import StateData
from direct.fsm import ClassicFSM, State
from direct.task import Task
from otp.distributed.TelemetryLimiter import RotationLimitToH, TLGatherAllAvs
from toontown.battle import BattleParticles
from toontown.building import Elevator
from toontown.hood import ZoneUtil
from toontown.toonbase import ToontownGlobals
from toontown.toon.Toon import teleportDebug
from toontown.estate import HouseGlobals
from toontown.toonbase import TTLocalizer
from direct.interval.IntervalGlobal import *
from otp.nametag import NametagGlobals
visualizeZones = base.config.GetBool('visualize-zones', 0)
class Street(BattlePlace.BattlePlace):
notify = DirectNotifyGlobal.directNotify.newCategory('Street')
def __init__(self, loader, parentFSM, doneEvent):
BattlePlace.BattlePlace.__init__(self, loader, doneEvent)
self.fsm = ClassicFSM.ClassicFSM('Street', [State.State('start', self.enterStart, self.exitStart, ['walk',
'tunnelIn',
'doorIn',
'teleportIn',
'elevatorIn']),
State.State('walk', self.enterWalk, self.exitWalk, ['push',
'sit',
'stickerBook',
'WaitForBattle',
'battle',
'doorOut',
'elevator',
'tunnelIn',
'tunnelOut',
'teleportOut',
'quest',
'stopped',
'fishing',
'purchase',
'died']),
State.State('sit', self.enterSit, self.exitSit, ['walk']),
State.State('push', self.enterPush, self.exitPush, ['walk']),
State.State('stickerBook', self.enterStickerBook, self.exitStickerBook, ['walk',
'push',
'sit',
'battle',
'doorOut',
'elevator',
'tunnelIn',
'tunnelOut',
'WaitForBattle',
'teleportOut',
'quest',
'stopped',
'fishing',
'purchase']),
State.State('WaitForBattle', self.enterWaitForBattle, self.exitWaitForBattle, ['battle', 'walk']),
State.State('battle', self.enterBattle, self.exitBattle, ['walk', 'teleportOut', 'died']),
State.State('doorIn', self.enterDoorIn, self.exitDoorIn, ['walk', 'stopped']),
State.State('doorOut', self.enterDoorOut, self.exitDoorOut, ['walk', 'stopped']),
State.State('elevatorIn', self.enterElevatorIn, self.exitElevatorIn, ['walk']),
State.State('elevator', self.enterElevator, self.exitElevator, ['walk']),
State.State('teleportIn', self.enterTeleportIn, self.exitTeleportIn, ['walk',
'teleportOut',
'quietZone',
'WaitForBattle',
'battle']),
State.State('teleportOut', self.enterTeleportOut, self.exitTeleportOut, ['teleportIn', 'quietZone', 'WaitForBattle']),
State.State('died', self.enterDied, self.exitDied, ['quietZone']),
State.State('tunnelIn', self.enterTunnelIn, self.exitTunnelIn, ['walk']),
State.State('tunnelOut', self.enterTunnelOut, self.exitTunnelOut, ['final']),
State.State('quietZone', self.enterQuietZone, self.exitQuietZone, ['teleportIn']),
State.State('quest', self.enterQuest, self.exitQuest, ['walk', 'stopped']),
State.State('stopped', self.enterStopped, self.exitStopped, ['walk']),
State.State('stopped', self.enterStopped, self.exitStopped, ['walk']),
State.State('fishing', self.enterFishing, self.exitFishing, ['walk']),
State.State('purchase', self.enterPurchase, self.exitPurchase, ['walk']),
State.State('final', self.enterFinal, self.exitFinal, ['start'])], 'start', 'final')
self.parentFSM = parentFSM
self.tunnelOriginList = []
self.elevatorDoneEvent = 'elevatorDone'
self.halloweenLights = []
self.zone = 0
def enter(self, requestStatus, visibilityFlag = 1, arrowsOn = 1):
teleportDebug(requestStatus, 'Street.enter(%s)' % (requestStatus,))
self._ttfToken = None
self.fsm.enterInitialState()
base.playMusic(self.loader.music, looping=1, volume=0.8)
self.loader.geom.reparentTo(render)
if visibilityFlag:
self.visibilityOn()
base.localAvatar.setGeom(self.loader.geom)
base.localAvatar.setOnLevelGround(1)
self._telemLimiter = TLGatherAllAvs('Street', RotationLimitToH)
NametagGlobals.setMasterArrowsOn(arrowsOn)
self.zone = ZoneUtil.getBranchZone(requestStatus['zoneId'])
def __lightDecorationOn__():
geom = base.cr.playGame.getPlace().loader.geom
self.halloweenLights = geom.findAllMatches('**/*light*')
self.halloweenLights += geom.findAllMatches('**/*lamp*')
self.halloweenLights += geom.findAllMatches('**/prop_snow_tree*')
for light in self.halloweenLights:
light.setColorScaleOff(1)
if base.cr.newsManager.isHolidayRunning(ToontownGlobals.HALLOWEEN) and self.loader.hood.spookySkyFile:
lightsOff = Sequence(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 0.1, Vec4(0.55, 0.55, 0.65, 1)), Func(self.loader.hood.startSpookySky))
lightsOff.start()
else:
self.loader.hood.startSky()
lightsOn = LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 0.1, Vec4(1, 1, 1, 1))
lightsOn.start()
self.accept('doorDoneEvent', self.handleDoorDoneEvent)
self.accept('DistributedDoor_doorTrigger', self.handleDoorTrigger)
self.enterZone(requestStatus['zoneId'])
self.tunnelOriginList = base.cr.hoodMgr.addLinkTunnelHooks(self, self.loader.nodeList)
self.fsm.request(requestStatus['how'], [requestStatus])
def exit(self, visibilityFlag = 1):
if visibilityFlag:
self.visibilityOff()
self.loader.geom.reparentTo(hidden)
self._telemLimiter.destroy()
del self._telemLimiter
def __lightDecorationOff__():
for light in self.halloweenLights:
light.reparentTo(hidden)
NametagGlobals.setMasterArrowsOn(0)
self.loader.hood.stopSky()
self.loader.music.stop()
base.localAvatar.setGeom(render)
base.localAvatar.setOnLevelGround(0)
def load(self):
BattlePlace.BattlePlace.load(self)
self.parentFSM.getStateNamed('street').addChild(self.fsm)
def unload(self):
self.parentFSM.getStateNamed('street').removeChild(self.fsm)
del self.parentFSM
del self.fsm
self.enterZone(None)
cleanupDialog('globalDialog')
self.ignoreAll()
BattlePlace.BattlePlace.unload(self)
return
def enterElevatorIn(self, requestStatus):
self._eiwbTask = taskMgr.add(Functor(self._elevInWaitBldgTask, requestStatus['bldgDoId']), uniqueName('elevInWaitBldg'))
def _elevInWaitBldgTask(self, bldgDoId, task):
bldg = base.cr.doId2do.get(bldgDoId)
if bldg:
if bldg.elevatorNodePath is not None:
if self._enterElevatorGotElevator():
return Task.done
return Task.cont
def _enterElevatorGotElevator(self):
if not messenger.whoAccepts('insideVictorElevator'):
return False
messenger.send('insideVictorElevator')
return True
def exitElevatorIn(self):
taskMgr.remove(self._eiwbTask)
def enterElevator(self, distElevator):
base.localAvatar.cantLeaveGame = 1
self.accept(self.elevatorDoneEvent, self.handleElevatorDone)
self.elevator = Elevator.Elevator(self.fsm.getStateNamed('elevator'), self.elevatorDoneEvent, distElevator)
self.elevator.load()
self.elevator.enter()
def exitElevator(self):
base.localAvatar.cantLeaveGame = 0
self.ignore(self.elevatorDoneEvent)
self.elevator.unload()
self.elevator.exit()
del self.elevator
def detectedElevatorCollision(self, distElevator):
self.fsm.request('elevator', [distElevator])
return None
def handleElevatorDone(self, doneStatus):
self.notify.debug('handling elevator done event')
where = doneStatus['where']
if where == 'reject':
if hasattr(base.localAvatar, 'elevatorNotifier') and base.localAvatar.elevatorNotifier.isNotifierOpen():
pass
else:
self.fsm.request('walk')
elif where == 'exit':
self.fsm.request('walk')
elif where in ('suitInterior', 'cogdoInterior'):
self.doneStatus = doneStatus
messenger.send(self.doneEvent)
else:
self.notify.error('Unknown mode: ' + where + ' in handleElevatorDone')
def enterTunnelIn(self, requestStatus):
self.enterZone(requestStatus['zoneId'])
BattlePlace.BattlePlace.enterTunnelIn(self, requestStatus)
def enterTeleportIn(self, requestStatus):
teleportDebug(requestStatus, 'Street.enterTeleportIn(%s)' % (requestStatus,))
zoneId = requestStatus['zoneId']
self._ttfToken = self.addSetZoneCompleteCallback(Functor(self._teleportToFriend, requestStatus))
self.enterZone(zoneId)
BattlePlace.BattlePlace.enterTeleportIn(self, requestStatus)
def _teleportToFriend(self, requestStatus):
avId = requestStatus['avId']
hoodId = requestStatus['hoodId']
zoneId = requestStatus['zoneId']
if avId != -1:
if avId not in base.cr.doId2do:
friend = base.cr.identifyAvatar(avId)
if friend == None:
teleportDebug(requestStatus, "couldn't find friend %s" % avId)
handle = base.cr.identifyFriend(avId)
requestStatus = {'how': 'teleportIn',
'hoodId': hoodId,
'zoneId': hoodId,
'shardId': None,
'loader': 'safeZoneLoader',
'where': 'playground',
'avId': avId}
self.fsm.request('final')
self.__teleportOutDone(requestStatus)
return
def exitTeleportIn(self):
self.removeSetZoneCompleteCallback(self._ttfToken)
self._ttfToken = None
BattlePlace.BattlePlace.exitTeleportIn(self)
return
def enterTeleportOut(self, requestStatus):
if 'battle' in requestStatus:
self.__teleportOutDone(requestStatus)
else:
BattlePlace.BattlePlace.enterTeleportOut(self, requestStatus, self.__teleportOutDone)
def __teleportOutDone(self, requestStatus):
hoodId = requestStatus['hoodId']
zoneId = requestStatus['zoneId']
shardId = requestStatus['shardId']
if hoodId == self.loader.hood.id and shardId == None:
if zoneId == self.zoneId:
self.fsm.request('teleportIn', [requestStatus])
elif requestStatus['where'] == 'street' and ZoneUtil.getBranchZone(zoneId) == self.loader.branchZone:
self.fsm.request('quietZone', [requestStatus])
else:
self.doneStatus = requestStatus
messenger.send(self.doneEvent)
elif hoodId == ToontownGlobals.MyEstate:
self.getEstateZoneAndGoHome(requestStatus)
else:
self.doneStatus = requestStatus
messenger.send(self.doneEvent)
return
def exitTeleportOut(self):
BattlePlace.BattlePlace.exitTeleportOut(self)
def goHomeFailed(self, task):
self.notifyUserGoHomeFailed()
self.ignore('setLocalEstateZone')
self.doneStatus['avId'] = -1
self.doneStatus['zoneId'] = self.getZoneId()
self.fsm.request('teleportIn', [self.doneStatus])
return Task.done
def renameFloorPolys(self, nodeList):
for i in nodeList:
collNodePaths = i.findAllMatches('**/+CollisionNode')
numCollNodePaths = collNodePaths.getNumPaths()
visGroupName = i.node().getName()
for j in xrange(numCollNodePaths):
collNodePath = collNodePaths.getPath(j)
bitMask = collNodePath.node().getIntoCollideMask()
if bitMask.getBit(1):
collNodePath.node().setName(visGroupName)
def hideAllVisibles(self):
for i in self.loader.nodeList:
i.stash()
def showAllVisibles(self):
for i in self.loader.nodeList:
i.unstash()
def visibilityOn(self):
self.hideAllVisibles()
self.accept('on-floor', self.enterZone)
def visibilityOff(self):
self.ignore('on-floor')
self.showAllVisibles()
def doEnterZone(self, newZoneId):
if self.zoneId != None:
for i in self.loader.nodeDict[self.zoneId]:
if newZoneId:
if i not in self.loader.nodeDict[newZoneId]:
self.loader.fadeOutDict[i].start()
self.loader.exitAnimatedProps(i)
else:
i.stash()
self.loader.exitAnimatedProps(i)
if newZoneId != None:
for i in self.loader.nodeDict[newZoneId]:
if self.zoneId:
if i not in self.loader.nodeDict[self.zoneId]:
self.loader.fadeInDict[i].start()
self.loader.enterAnimatedProps(i)
else:
if self.loader.fadeOutDict[i].isPlaying():
self.loader.fadeOutDict[i].finish()
if self.loader.fadeInDict[i].isPlaying():
self.loader.fadeInDict[i].finish()
self.loader.enterAnimatedProps(i)
i.unstash()
if newZoneId != self.zoneId:
if visualizeZones:
if self.zoneId != None:
self.loader.zoneDict[self.zoneId].clearColor()
if newZoneId != None:
self.loader.zoneDict[newZoneId].setColor(0, 0, 1, 1, 100)
if newZoneId is not None:
loader = base.cr.playGame.getPlace().loader
if newZoneId in loader.zoneVisDict:
base.cr.sendSetZoneMsg(newZoneId, loader.zoneVisDict[newZoneId])
else:
visList = [newZoneId] + loader.zoneVisDict.values()[0]
base.cr.sendSetZoneMsg(newZoneId, visList)
self.zoneId = newZoneId
geom = base.cr.playGame.getPlace().loader.geom
self.halloweenLights = geom.findAllMatches('**/*light*')
self.halloweenLights += geom.findAllMatches('**/*lamp*')
self.halloweenLights += geom.findAllMatches('**/prop_snow_tree*')
for light in self.halloweenLights:
light.setColorScaleOff(1)