oldschool-toontown/toontown/town/TownLoader.py

380 lines
16 KiB
Python
Raw Normal View History

from panda3d.core import *
2019-11-02 17:27:54 -05:00
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
from . import TownBattle
2019-11-02 17:27:54 -05:00
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
from toontown.hood import ZoneUtil
from direct.interval.IntervalGlobal import *
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.loader.loadMusic(self.musicFile)
self.activityMusic = base.loader.loadMusic(self.activityMusicFile)
2020-01-14 13:28:52 -06:00
self.battleMusic = base.loader.loadMusic('phase_3.5/audio/bgm/encntr_general_bg.ogg')
2019-11-02 17:27:54 -05:00
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
2021-06-29 12:57:22 -05:00
if __astron__:
del self.node2zone
2019-11-02 17:27:54 -05:00
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:
loader.loadDNAFile(self.hood.dnaStore, 'phase_5/dna/storage_town.dna')
self.notify.debug('done loading %s' % 'phase_5/dna/storage_town.dna')
loader.loadDNAFile(self.hood.dnaStore, self.townStorageDNAFile)
self.notify.debug('done loading %s' % self.townStorageDNAFile)
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 range(npl.getNumPaths()):
np = npl.getPath(i)
np.setTag('transformIndex', repr(i))
2019-11-02 17:27:54 -05:00
self.holidayPropTransforms[i] = np.getNetTransform()
self.notify.info('skipping self.geom.flattenMedium')
gsg = base.win.getGsg()
if gsg:
self.geom.prepareScene(gsg)
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 range(npc.getNumPaths()):
nodePath = npc.getPath(i)
nodePath.wrtReparentTo(bucket)
npc = self.geom.findAllMatches('**/sb*:*animated_building*_DNARoot')
for i in range(npc.getNumPaths()):
nodePath = npc.getPath(i)
nodePath.wrtReparentTo(bucket)
def makeDictionaries(self, dnaStore):
self.nodeDict = {}
self.zoneDict = {}
2021-06-29 12:57:22 -05:00
if __astron__:
self.node2zone = {}
2019-11-02 17:27:54 -05:00
self.nodeList = []
self.fadeInDict = {}
self.fadeOutDict = {}
a1 = Vec4(1, 1, 1, 1)
a0 = Vec4(1, 1, 1, 0)
numVisGroups = dnaStore.getNumDNAVisGroups()
for i in range(numVisGroups):
groupFullName = dnaStore.getDNAVisGroupName(i)
groupName = base.cr.hoodMgr.extractGroupName(groupFullName)
zoneId = int(groupName)
zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId)
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)
self.nodeDict[zoneId] = []
self.nodeList.append(groupNode)
self.zoneDict[zoneId] = groupNode
2021-06-29 12:57:22 -05:00
if __astron__:
self.node2zone[groupNode] = zoneId
2019-11-02 17:27:54 -05:00
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 range(numVisGroups):
groupFullName = dnaStore.getDNAVisGroupName(i)
zoneId = int(base.cr.hoodMgr.extractGroupName(groupFullName))
zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId)
for j in range(dnaStore.getNumVisiblesInDNAVisGroup(i)):
visName = dnaStore.getVisibleName(i, j)
groupName = base.cr.hoodMgr.extractGroupName(visName)
nextZoneId = int(groupName)
nextZoneId = ZoneUtil.getTrueZoneId(nextZoneId, self.zoneId)
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 range(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 range(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_*')
numInteractivePropNodes = interactivePropNodes.getNumPaths()
for j in range(numInteractivePropNodes):
interactivePropNode = interactivePropNodes.getPath(j)
className = 'InteractiveAnimatedProp'
if 'hydrant' in interactivePropNode.getName():
className = 'HydrantInteractiveProp'
elif 'trashcan' in interactivePropNode.getName():
className = 'TrashcanInteractiveProp'
elif 'mailbox' in interactivePropNode.getName():
className = 'MailboxInteractiveProp'
symbols = {}
base.cr.importModule(symbols, 'toontown.hood', [className])
classObj = getattr(symbols[className], className)
interactivePropObj = classObj(interactivePropNode)
animPropList = self.animPropDict.get(i)
if animPropList is None:
animPropList = self.animPropDict.setdefault(i, [])
animPropList.append(interactivePropObj)
if interactivePropObj.getCellIndex() == 0:
zoneId = int(i.getName())
if zoneId not in self.zoneIdToInteractivePropDict:
self.zoneIdToInteractivePropDict[zoneId] = interactivePropObj
else:
self.notify.error('already have interactive prop %s in zone %s' % (self.zoneIdToInteractivePropDict, zoneId))
animatedBuildingNodes = i.findAllMatches('**/*:animated_building_*;-h')
for np in animatedBuildingNodes:
if np.getName().startswith('sb'):
animatedBuildingNodes.removePath(np)
numAnimatedBuildingNodes = animatedBuildingNodes.getNumPaths()
for j in range(numAnimatedBuildingNodes):
animatedBuildingNode = animatedBuildingNodes.getPath(j)
className = 'GenericAnimatedBuilding'
symbols = {}
base.cr.importModule(symbols, 'toontown.hood', [className])
classObj = getattr(symbols[className], className)
animatedBuildingObj = classObj(animatedBuildingNode)
animPropList = self.animPropDict.get(i)
if animPropList is None:
animPropList = self.animPropDict.setdefault(i, [])
animPropList.append(animatedBuildingObj)
return
def deleteAnimatedProps(self):
for zoneNode, animPropList in list(self.animPropDict.items()):
2019-11-02 17:27:54 -05:00
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):
result = None
if zoneId in self.zoneIdToInteractivePropDict:
result = self.zoneIdToInteractivePropDict[zoneId]
return result