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

347 lines
14 KiB
Python

from panda3d.core import *
from toontown.battle.BattleProps import *
from toontown.battle.BattleSounds import *
from toontown.distributed.ToontownMsgTypes import *
from toontown.toonbase.ToontownGlobals import *
from direct.gui.DirectGui import cleanupDialog
from direct.directnotify import DirectNotifyGlobal
from toontown.hood import Place
from direct.showbase import DirectObject
from direct.fsm import StateData
from direct.fsm import ClassicFSM, State
from direct.fsm import State
from direct.task import Task
import TownBattle
from toontown.toon import Toon
from toontown.toon.Toon import teleportDebug
from toontown.battle import BattleParticles
from direct.fsm import StateData
from toontown.building import ToonInterior
from toontown.hood import QuietZoneState, ZoneUtil, HydrantInteractiveProp, MailboxInteractiveProp, TrashcanInteractiveProp
from direct.interval.IntervalGlobal import *
from toontown.dna.DNAParser import DNABulkLoader
class TownLoader(StateData.StateData):
notify = DirectNotifyGlobal.directNotify.newCategory('TownLoader')
def __init__(self, hood, parentFSMState, doneEvent):
StateData.StateData.__init__(self, doneEvent)
self.hood = hood
self.parentFSMState = parentFSMState
self.fsm = ClassicFSM.ClassicFSM('TownLoader', [State.State('start', self.enterStart, self.exitStart, ['quietZone', 'street', 'toonInterior']),
State.State('street', self.enterStreet, self.exitStreet, ['quietZone']),
State.State('toonInterior', self.enterToonInterior, self.exitToonInterior, ['quietZone']),
State.State('quietZone', self.enterQuietZone, self.exitQuietZone, ['street', 'toonInterior']),
State.State('final', self.enterFinal, self.exitFinal, ['start'])], 'start', 'final')
self.branchZone = None
self.canonicalBranchZone = None
self.placeDoneEvent = 'placeDone'
self.townBattleDoneEvent = 'town-battle-done'
return
def loadBattleAnims(self):
Toon.loadBattleAnims()
def unloadBattleAnims(self):
Toon.unloadBattleAnims()
def load(self, zoneId):
self.zoneId = zoneId
self.parentFSMState.addChild(self.fsm)
self.loadBattleAnims()
self.branchZone = ZoneUtil.getBranchZone(zoneId)
self.canonicalBranchZone = ZoneUtil.getCanonicalBranchZone(zoneId)
self.music = base.loadMusic(self.musicFile)
self.activityMusic = base.loadMusic(self.activityMusicFile)
self.battleMusic = base.loadMusic('phase_3.5/audio/bgm/encntr_general_bg.ogg')
self.townBattle = TownBattle.TownBattle(self.townBattleDoneEvent)
self.townBattle.load()
def unload(self):
self.unloadBattleAnims()
globalPropPool.unloadProps()
globalBattleSoundCache.clear()
BattleParticles.unloadParticles()
self.parentFSMState.removeChild(self.fsm)
del self.parentFSMState
del self.fsm
del self.streetClass
self.landmarkBlocks.removeNode()
del self.landmarkBlocks
self.hood.dnaStore.resetSuitPoints()
self.hood.dnaStore.resetBattleCells()
del self.hood
del self.nodeDict
del self.zoneDict
del self.fadeInDict
del self.fadeOutDict
del self.nodeList
self.geom.removeNode()
del self.geom
self.townBattle.unload()
self.townBattle.cleanup()
del self.townBattle
del self.battleMusic
del self.music
del self.activityMusic
del self.holidayPropTransforms
self.deleteAnimatedProps()
cleanupDialog('globalDialog')
ModelPool.garbageCollect()
TexturePool.garbageCollect()
def enter(self, requestStatus):
teleportDebug(requestStatus, 'TownLoader.enter(%s)' % requestStatus)
self.fsm.enterInitialState()
teleportDebug(requestStatus, 'setting state: %s' % requestStatus['where'])
self.setState(requestStatus['where'], requestStatus)
def exit(self):
self.ignoreAll()
def setState(self, stateName, requestStatus):
self.fsm.request(stateName, [requestStatus])
def enterStart(self):
pass
def exitStart(self):
pass
def enterStreet(self, requestStatus):
teleportDebug(requestStatus, 'enterStreet(%s)' % requestStatus)
self.acceptOnce(self.placeDoneEvent, self.streetDone)
self.place = self.streetClass(self, self.fsm, self.placeDoneEvent)
self.place.load()
base.cr.playGame.setPlace(self.place)
self.place.enter(requestStatus)
def exitStreet(self):
self.place.exit()
self.place.unload()
self.place = None
base.cr.playGame.setPlace(self.place)
return
def streetDone(self):
self.requestStatus = self.place.doneStatus
status = self.place.doneStatus
if status['loader'] == 'townLoader' and ZoneUtil.getBranchZone(status['zoneId']) == self.branchZone and status['shardId'] == None:
self.fsm.request('quietZone', [status])
else:
self.doneStatus = status
messenger.send(self.doneEvent)
return
def enterToonInterior(self, requestStatus):
self.acceptOnce(self.placeDoneEvent, self.handleToonInteriorDone)
self.place = ToonInterior.ToonInterior(self, self.fsm.getStateNamed('toonInterior'), self.placeDoneEvent)
base.cr.playGame.setPlace(self.place)
self.place.load()
self.place.enter(requestStatus)
def exitToonInterior(self):
self.ignore(self.placeDoneEvent)
self.place.exit()
self.place.unload()
self.place = None
base.cr.playGame.setPlace(self.place)
return
def handleToonInteriorDone(self):
status = self.place.doneStatus
if ZoneUtil.getBranchZone(status['zoneId']) == self.branchZone and status['shardId'] == None:
self.fsm.request('quietZone', [status])
else:
self.doneStatus = status
messenger.send(self.doneEvent)
return
def enterQuietZone(self, requestStatus):
self.quietZoneDoneEvent = uniqueName('quietZoneDone')
self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone)
self.quietZoneStateData = QuietZoneState.QuietZoneState(self.quietZoneDoneEvent)
self.quietZoneStateData.load()
self.quietZoneStateData.enter(requestStatus)
def exitQuietZone(self):
self.ignore(self.quietZoneDoneEvent)
del self.quietZoneDoneEvent
self.quietZoneStateData.exit()
self.quietZoneStateData.unload()
self.quietZoneStateData = None
return
def handleQuietZoneDone(self):
status = self.quietZoneStateData.getRequestStatus()
self.fsm.request(status['where'], [status])
def enterFinal(self):
pass
def exitFinal(self):
pass
def createHood(self, dnaFile, loadStorage = 1):
if loadStorage:
files = ('phase_5/dna/storage_town.pdna', self.townStorageDNAFile)
dnaBulk = DNABulkLoader(self.hood.dnaStore, files)
dnaBulk.loadDNAFiles()
node = loader.loadDNAFile(self.hood.dnaStore, dnaFile)
self.notify.debug('done loading %s' % dnaFile)
if node.getNumParents() == 1:
self.geom = NodePath(node.getParent(0))
self.geom.reparentTo(hidden)
else:
self.geom = hidden.attachNewNode(node)
self.makeDictionaries(self.hood.dnaStore)
self.reparentLandmarkBlockNodes()
self.renameFloorPolys(self.nodeList)
self.createAnimatedProps(self.nodeList)
self.holidayPropTransforms = {}
npl = self.geom.findAllMatches('**/=DNARoot=holiday_prop')
for i in xrange(npl.getNumPaths()):
np = npl.getPath(i)
np.setTag('transformIndex', `i`)
self.holidayPropTransforms[i] = np.getNetTransform()
gsg = base.win.getGsg()
if gsg:
self.geom.prepareScene(gsg)
self.geom.flattenLight()
self.geom.setName('town_top_level')
def reparentLandmarkBlockNodes(self):
bucket = self.landmarkBlocks = hidden.attachNewNode('landmarkBlocks')
npc = self.geom.findAllMatches('**/sb*:*_landmark_*_DNARoot')
for i in xrange(npc.getNumPaths()):
nodePath = npc.getPath(i)
nodePath.wrtReparentTo(bucket)
def makeDictionaries(self, dnaStore):
self.nodeDict = {}
self.zoneDict = {}
self.zoneVisDict = {}
self.nodeList = []
self.fadeInDict = {}
self.fadeOutDict = {}
a1 = Vec4(1, 1, 1, 1)
a0 = Vec4(1, 1, 1, 0)
numVisGroups = dnaStore.getNumDNAVisGroupsAI()
for i in xrange(numVisGroups):
groupFullName = dnaStore.getDNAVisGroupName(i)
visGroup = dnaStore.getDNAVisGroupAI(i)
groupName = base.cr.hoodMgr.extractGroupName(groupFullName)
zoneId = int(groupName)
groupNode = self.geom.find('**/' + groupFullName)
if groupNode.isEmpty():
self.notify.error('Could not find visgroup')
else:
if ':' in groupName:
groupName = '%s%s' % (zoneId, groupName[groupName.index(':'):])
else:
groupName = '%s' % zoneId
groupNode.setName(groupName)
groupNode.flattenMedium()
self.nodeDict[zoneId] = []
self.nodeList.append(groupNode)
self.zoneDict[zoneId] = groupNode
visibles = []
for i in xrange(visGroup.getNumVisibles()):
visibles.append(int(visGroup.getVisible(i)))
visibles.append(ZoneUtil.getBranchZone(zoneId))
self.zoneVisDict[zoneId] = visibles
fadeDuration = 0.5
self.fadeOutDict[groupNode] = Sequence(Func(groupNode.setTransparency, 1), LerpColorScaleInterval(groupNode, fadeDuration, a0, startColorScale=a1), Func(groupNode.clearColorScale), Func(groupNode.clearTransparency), Func(groupNode.stash), name='fadeZone-' + str(zoneId), autoPause=1)
self.fadeInDict[groupNode] = Sequence(Func(groupNode.unstash), Func(groupNode.setTransparency, 1), LerpColorScaleInterval(groupNode, fadeDuration, a1, startColorScale=a0), Func(groupNode.clearColorScale), Func(groupNode.clearTransparency), name='fadeZone-' + str(zoneId), autoPause=1)
for i in xrange(numVisGroups):
groupFullName = dnaStore.getDNAVisGroupName(i)
zoneId = int(base.cr.hoodMgr.extractGroupName(groupFullName))
for j in xrange(dnaStore.getNumVisiblesInDNAVisGroup(i)):
visName = dnaStore.getVisibleName(i, j)
groupName = base.cr.hoodMgr.extractGroupName(visName)
nextZoneId = int(groupName)
visNode = self.zoneDict[nextZoneId]
self.nodeDict[zoneId].append(visNode)
self.hood.dnaStore.resetPlaceNodes()
self.hood.dnaStore.resetDNAGroups()
self.hood.dnaStore.resetDNAVisGroups()
self.hood.dnaStore.resetDNAVisGroupsAI()
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 createAnimatedProps(self, nodeList):
self.animPropDict = {}
self.zoneIdToInteractivePropDict = {}
for i in nodeList:
animPropNodes = i.findAllMatches('**/animated_prop_*')
numAnimPropNodes = animPropNodes.getNumPaths()
for j in xrange(numAnimPropNodes):
animPropNode = animPropNodes.getPath(j)
if animPropNode.getName().startswith('animated_prop_generic'):
className = 'GenericAnimatedProp'
elif animPropNode.getName().startswith('animated_prop_'):
name = animPropNode.getName()[len('animated_prop_'):]
splits = name.split('_')
className = splits[0]
else:
className = animPropNode.getName()[14:-8]
symbols = {}
base.cr.importModule(symbols, 'toontown.hood', [className])
classObj = getattr(symbols[className], className)
animPropObj = classObj(animPropNode)
animPropList = self.animPropDict.setdefault(i, [])
animPropList.append(animPropObj)
interactivePropNodes = i.findAllMatches('**/interactive_prop_*')
for j in xrange(interactivePropNodes.getNumPaths()):
propNode = interactivePropNodes.getPath(j)
propName = propNode.getName()
if 'hydrant' in propName:
prop = HydrantInteractiveProp.HydrantInteractiveProp(propNode)
elif 'trashcan' in propName:
prop = TrashcanInteractiveProp.TrashcanInteractiveProp(propNode)
elif 'mailbox' in propName:
prop = MailboxInteractiveProp.MailboxInteractiveProp(propNode)
else:
continue
if i in self.animPropDict:
self.animPropDict[i].append(prop)
else:
self.animPropDict[i] = [prop]
self.zoneIdToInteractivePropDict[int(i.getName())] = prop
def deleteAnimatedProps(self):
for zoneNode, animPropList in self.animPropDict.items():
for animProp in animPropList:
animProp.delete()
del self.animPropDict
def enterAnimatedProps(self, zoneNode):
for animProp in self.animPropDict.get(zoneNode, ()):
animProp.enter()
def exitAnimatedProps(self, zoneNode):
for animProp in self.animPropDict.get(zoneNode, ()):
animProp.exit()
def getInteractiveProp(self, zoneId):
if zoneId in self.zoneIdToInteractivePropDict:
return self.zoneIdToInteractivePropDict[zoneId]
return None