oldschool-toontown/toontown/cogdominium/CogdoFlyingLevel.py

244 lines
9.8 KiB
Python
Raw Normal View History

from panda3d.core import NodePath, Plane, Vec3, Point3
from panda3d.core import CollisionPlane, CollisionNode
2019-11-02 17:27:54 -05:00
from direct.showbase.RandomNumGen import RandomNumGen
from direct.showbase.DirectObject import DirectObject
from direct.showbase.PythonUtil import bound as clamp
from . import CogdoUtil
from . import CogdoFlyingGameGlobals as Globals
from .CogdoFlyingLevelQuadrant import CogdoFlyingLevelQuadrant
from .CogdoFlyingObjects import CogdoFlyingGatherableFactory, CogdoFlyingPlatform, CogdoFlyingLevelFog
from .CogdoFlyingObstacles import CogdoFlyingObtacleFactory
from .CogdoGameExit import CogdoGameExit
2019-11-02 17:27:54 -05:00
from otp.otpbase import OTPGlobals
class CogdoFlyingLevel(DirectObject):
notify = directNotify.newCategory('CogdoFlyingLevel')
def __init__(self, parent, frameModel, startPlatformModel, endPlatformModel, quadLengthUnits, quadVisibilityAhead, quadVisibiltyBehind):
self.parent = parent
self.quadLengthUnits = quadLengthUnits
self._halfQuadLengthUnits = quadLengthUnits / 2.0
self.quadVisibiltyAhead = quadVisibilityAhead
self.quadVisibiltyBehind = quadVisibiltyBehind
self._frameModel = frameModel
self.root = NodePath('CogdoFlyingLevel')
self.quadrantRoot = NodePath('QuadrantsRoot')
self.quadrantRoot.reparentTo(self.root)
self._startPlatformModel = startPlatformModel
self._startPlatformModel.reparentTo(self.root)
self._startPlatformModel.setZ(Globals.Level.StartPlatformHeight)
self._endPlatformModel = endPlatformModel
self._endPlatformModel.reparentTo(self.root)
self._endPlatformModel.setZ(Globals.Level.EndPlatformHeight)
self.wallR = self._frameModel.find('**/wallR')
self.wallL = self._frameModel.find('**/wallL')
self._exit = CogdoGameExit()
self._exit.reparentTo(self._endPlatformModel)
loc = self._endPlatformModel.find('**/exit_loc')
offset = loc.getPos(render)
self._exit.setPos(render, offset)
self.quadrants = []
self.visibleQuadIndices = []
self._numQuads = 0
self._currentQuadNum = -1
self._camera = None
self._initCollisions()
self.upLimit = self._frameModel.find('**/limit_up').getZ(render)
self.downLimit = self._frameModel.find('**/limit_down').getZ(render)
self.leftLimit = self._frameModel.find('**/limit_left').getX(render) - 30.0
self.rightLimit = self._frameModel.find('**/limit_right').getX(render) + 30.0
self.backLimit = -self.quadLengthUnits
self.forwardLimit = self.quadLengthUnits * 20
self._frameModel.flattenStrong()
self.gatherableFactory = CogdoFlyingGatherableFactory()
self.obstacleFactory = CogdoFlyingObtacleFactory()
return
def getExit(self):
return self._exit
def getBounds(self):
return ((self.leftLimit, self.rightLimit), (self.backLimit, self.forwardLimit), (self.downLimit, self.upLimit))
def getGatherable(self, serialNum):
for quadrant in self.quadrants:
for gatherable in quadrant.gatherables:
if gatherable.serialNum == serialNum:
return gatherable
return None
def ready(self):
self.gatherableFactory.destroy()
del self.gatherableFactory
self.obstacleFactory.destroy()
del self.obstacleFactory
self._initStartEndPlatforms()
self._frameModel.reparentTo(self.root)
self.root.reparentTo(self.parent)
self.root.stash()
def _initStartEndPlatforms(self):
self.startPlatform = CogdoFlyingPlatform(self._startPlatformModel, Globals.Level.PlatformTypes.StartPlatform)
self.endPlatform = CogdoFlyingPlatform(self._endPlatformModel, Globals.Level.PlatformTypes.EndPlatform)
self._endPlatformModel.setY(self.convertQuadNumToY(self._numQuads))
self.backLimit = self._startPlatformModel.getY(render) - Globals.Level.StartPlatformLength * 0.7
self.forwardLimit = self._endPlatformModel.getY(render) + Globals.Level.EndPlatformLength * 0.7
def _initCollisions(self):
self.collPlane = CollisionPlane(Plane(Vec3(0, 0, 1.0), Point3(0, 0, 10)))
self.collPlane.setTangible(0)
self.collNode = CollisionNode('fogPlane')
self.collNode.setIntoCollideMask(OTPGlobals.FloorBitmask)
self.collNode.addSolid(self.collPlane)
self.collNodePath = self.root.attachNewNode(self.collNode)
self.collNodePath.hide()
def destroy(self):
del self.collPlane
self.collNodePath.removeNode()
del self.collNodePath
del self.collNode
for quadrant in self.quadrants:
quadrant.destroy()
self._exit.destroy()
del self._exit
self.root.removeNode()
del self.root
def onstage(self):
self.root.unstash()
self.update(0.0)
def offstage(self):
self.root.stash()
def start(self, startTime = 0.0):
self._startTime = startTime
def stop(self):
pass
def getLength(self):
return self.quadLengthUnits * self.getNumQuadrants()
def appendQuadrant(self, model):
quadrant = CogdoFlyingLevelQuadrant(self._numQuads, model, self, self.root)
if self._numQuads == 0:
quadrant.generateGatherables(self._startPlatformModel)
quadrant.offstage()
self.quadrants.append(quadrant)
self._numQuads = len(self.quadrants)
def getNumQuadrants(self):
return self._numQuads
def setCamera(self, camera):
self._camera = camera
def getCameraActualQuadrant(self):
camY = self._camera.getY(render)
y = self.root.getY(render)
return self.convertYToQuadNum(camY - y)
def update(self, dt = 0.0):
if self._camera is None:
return
quadNum = clamp(self.getCameraActualQuadrant(), 0, self._numQuads - 1)
if quadNum < self._numQuads:
self.quadrants[quadNum].update(dt)
if quadNum + 1 < self._numQuads:
self.quadrants[quadNum + 1].update(dt)
if quadNum != self._currentQuadNum:
self._switchToQuadrant(quadNum)
return
def _switchToQuadrant(self, quadNum):
self.visibleQuadIndices = []
if quadNum >= 0:
if quadNum > 0:
self.quadrants[max(quadNum - self.quadVisibiltyBehind, 0)].onstage()
for i in range(quadNum, min(quadNum + self.quadVisibiltyAhead + 1, self._numQuads)):
self.quadrants[i].onstage()
self.visibleQuadIndices.append(i)
if i == 0:
self.startPlatform.onstage()
elif i == self._numQuads - 1:
self.endPlatform.onstage()
self._currentQuadNum = quadNum
for i in list(range(0, max(self._currentQuadNum - self.quadVisibiltyBehind, 0))) + list(range(min(self._currentQuadNum + self.quadVisibiltyAhead + 1, self._numQuads), self._numQuads)):
2019-11-02 17:27:54 -05:00
self.quadrants[i].offstage()
if i == 0:
self.startPlatform.offstage()
elif i == self._numQuads - 1:
self.endPlatform.offstage()
def convertQuadNumToY(self, quadNum):
return quadNum * self.quadLengthUnits
def convertYToQuadNum(self, y):
return int(y / self.quadLengthUnits)
def convertCenterYToQuadNum(self, y):
return self.convertYToQuadNum(y + self._halfQuadLengthUnits)
class CogdoFlyingLevelFactory:
def __init__(self, parent, quadLengthUnits, quadVisibilityAhead, quadVisibiltyBehind, rng = None):
self.parent = parent
self.quadLengthUnits = quadLengthUnits
self.quadVisibiltyAhead = quadVisibilityAhead
self.quadVisibiltyBehind = quadVisibiltyBehind
self._rng = rng or RandomNumGen(1)
self._level = None
return
def loadAndBuildLevel(self, safezoneId):
levelNode = NodePath('level')
frameModel = CogdoUtil.loadFlyingModel('level')
startPlatformModel = CogdoUtil.loadFlyingModel('levelStart')
endPlatformModel = CogdoUtil.loadFlyingModel('levelEnd')
for fan in frameModel.findAllMatches('**/*wallFan'):
fan.flattenStrong()
frameModel.find('**/fogOpaque').setBin('background', 1)
frameModel.find('**/ceiling').setBin('background', 2)
frameModel.find('**/fogTranslucent_bm').setBin('fixed', 1)
frameModel.find('**/wallR').setBin('opaque', 2)
frameModel.find('**/wallL').setBin('opaque', 2)
frameModel.find('**/fogTranslucent_top').setBin('fixed', 2)
frameModel.getChildren().reparentTo(levelNode)
levelNode.hide()
self._level = CogdoFlyingLevel(self.parent, levelNode, startPlatformModel, endPlatformModel, self.quadLengthUnits, self.quadVisibiltyAhead, self.quadVisibiltyBehind)
if Globals.Dev.WantTempLevel:
quads = Globals.Dev.DevQuadsOrder
else:
levelInfo = Globals.Level.DifficultyOrder[safezoneId]
quads = []
for difficulty in levelInfo:
quadList = Globals.Level.QuadsByDifficulty[difficulty]
quads.append(quadList[self._rng.randint(0, len(quadList) - 1)])
for i in quads:
filePath = CogdoUtil.getModelPath('quadrant%i' % i, 'flying')
quadModel = loader.loadModel(filePath)
for np in quadModel.findAllMatches('**/*lightCone*'):
CogdoUtil.initializeLightCone(np, 'fixed', 3)
self._level.appendQuadrant(quadModel)
self._level.ready()
def createLevel(self, safezoneId = 2000):
if self._level is None:
self.loadAndBuildLevel(safezoneId)
return self._level
def createLevelFog(self):
if self._level is None:
self.loadAndBuildLevel()
return CogdoFlyingLevelFog(self._level)