Poodletooth-iLand/toontown/cogdominium/CogdoFlyingObstacles.py

393 lines
15 KiB
Python

import random
from direct.showbase.DirectObject import DirectObject
from direct.interval.IntervalGlobal import LerpFunc, ActorInterval, LerpPosInterval
from direct.interval.MetaInterval import Sequence
from direct.directutil import Mopath
from direct.showbase import PythonUtil
from panda3d.core import *
from toontown.toonbase import ToontownGlobals
from toontown.suit import Suit
from toontown.suit import SuitDNA
from toontown.battle import BattleProps
import CogdoUtil
import CogdoFlyingGameGlobals as Globals
from CogdoFlyingUtil import swapAvatarShadowPlacer
from direct.particles import ParticleEffect
from direct.particles import Particles
from direct.particles import ForceGroup
class CogdoFlyingObstacleFactory:
def __init__(self):
self._index = -1
self._whirlwindModel = CogdoUtil.loadFlyingModel('whirlwind').find('**/whirlwind')
self._fanModel = CogdoUtil.loadFlyingModel('streamer').find('**/streamer')
def destroy(self):
self._whirlwindModel.removeNode()
del self._whirlwindModel
self._fanModel.removeNode()
del self._fanModel
if Globals.Level.AddParticlesToStreamers:
if hasattr(self, 'f'):
self.f.cleanup()
del self.f
def createFan(self):
self._index += 1
return CogdoFlyingFan(self._index, self._fanModel)
def createFlyingMinion(self, motionPath = None):
self._index += 1
return CogdoFlyingMinionFlying(self._index, motionPath=motionPath)
def createWalkingMinion(self, motionPath = None):
self._index += 1
return CogdoFlyingMinionWalking(self._index, motionPath=motionPath)
def createWhirlwind(self, motionPath = None):
self._index += 1
return CogdoFlyingWhirlwind(self._index, self._whirlwindModel, motionPath=motionPath)
def createStreamerParticles(self, color1, color2, amp):
self.f = ParticleEffect.ParticleEffect('streamer_particles')
p0 = Particles.Particles('particles-1')
p0.setFactory('PointParticleFactory')
p0.setRenderer('SparkleParticleRenderer')
p0.setEmitter('RingEmitter')
p0.setPoolSize(80)
p0.setBirthRate(0.05)
p0.setLitterSize(100)
p0.setLitterSpread(0)
p0.factory.setLifespanBase(3.0)
p0.factory.setLifespanSpread(0.5)
p0.factory.setMassBase(1.0)
p0.factory.setMassSpread(0.0)
p0.factory.setTerminalVelocityBase(5.0)
p0.factory.setTerminalVelocitySpread(1.0)
p0.renderer.setAlphaMode(BaseParticleRenderer.PRALPHAOUT)
p0.renderer.setUserAlpha(1.0)
p0.renderer.setCenterColor(color1)
p0.renderer.setEdgeColor(color2)
p0.renderer.setBirthRadius(0.3)
p0.renderer.setDeathRadius(0.3)
p0.renderer.setLifeScale(SparkleParticleRenderer.SPNOSCALE)
p0.emitter.setEmissionType(BaseParticleEmitter.ETRADIATE)
p0.emitter.setAmplitude(0)
p0.emitter.setAmplitudeSpread(0)
f0 = ForceGroup.ForceGroup('Gravity')
force0 = LinearVectorForce(Vec3(0.0, 0.0, 10.0), 1.0, 0)
force0.setVectorMasks(1, 1, 1)
force0.setActive(1)
f0.addForce(force0)
self.f.addForceGroup(f0)
p0.emitter.setRadius(5.0)
self.f.addParticles(p0)
self.f.setPos(0, 0, 0)
self.f.setHpr(0, 0, 0)
return self.f
class CogdoFlyingObstacle(DirectObject):
EnterEventName = 'CogdoFlyingObstacle_Enter'
ExitEventName = 'CogdoFlyingObstacle_Exit'
MotionTypes = PythonUtil.Enum(('BackForth', 'Loop'))
def __init__(self, type, index, model, collSolid, motionPath = None, motionPattern = None, blendMotion = True, instanceModel = True):
self.type = type
self.index = index
name = 'CogdoFlyingObstacle-%s-%i' % (self.type, self.index)
if instanceModel:
self.model = NodePath(name)
model.instanceTo(self.model)
else:
self.model = model
self.model.setName(name)
self.currentT = 0.0
self.direction = 1.0
self.collNode = None
self._initCollisions(name, collSolid)
self.motionPath = motionPath
self.motionPattern = motionPattern
self.motionSequence = None
if blendMotion:
blendType = 'easeInOut'
else:
blendType = 'noBlend'
if motionPath is not None:
def moveObstacle(value):
self.motionPath.goTo(self.model, value)
self.motionPath = Mopath.Mopath(name='obstacle-%i' % self.index)
self.motionPath.loadNodePath(motionPath)
dur = self.motionPath.getMaxT()
self.motionSequence = Sequence(name='%s.obstacle-%i-motionSequence' % (self.__class__.__name__, self.index))
movePart1 = LerpFunc(moveObstacle, fromData=0.0, toData=self.motionPath.getMaxT(), duration=dur, blendType=blendType)
self.motionSequence.append(movePart1)
if self.motionPattern == CogdoFlyingObstacle.MotionTypes.BackForth:
movePart2 = LerpFunc(moveObstacle, fromData=self.motionPath.getMaxT(), toData=0.0, duration=dur, blendType=blendType)
self.motionSequence.append(movePart2)
return
def _initCollisions(self, name, collSolid):
self.collName = name
self.collSolid = collSolid
self.collSolid.setTangible(0)
self.collNode = CollisionNode(self.collName)
self.collNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
self.collNode.addSolid(self.collSolid)
self.collNodePath = self.model.attachNewNode(self.collNode)
self.collNodePath.hide()
self.accept('enter' + self.collName, self._handleEnterCollision)
self.accept('exit' + self.collName, self._handleExitCollision)
def disable(self):
if self.collNode is not None:
self.collNode.setIntoCollideMask(BitMask32(0))
return
def enable(self):
if self.collNode is not None:
self.collNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
return
def startMoving(self, elapsedTime = 0.0):
if self.motionSequence is not None:
self.motionSequence.loop()
self.motionSequence.setT(elapsedTime % self.motionSequence.getDuration())
return
def stopMoving(self):
if self.motionSequence is not None:
self.motionSequence.pause()
return
def destroy(self):
self.ignoreAll()
if self.motionSequence is not None:
self.motionSequence.clearToInitial()
del self.motionSequence
del self.collSolid
self.collNodePath.removeNode()
del self.collNodePath
del self.collNode
self.model.removeNode()
del self.model
del self.motionPath
return
def update(self, dt):
pass
def hide(self):
self.ignoreAll()
self.model.hide()
self.collNode.setIntoCollideMask(BitMask32(0))
def _handleEnterCollision(self, collEntry):
messenger.send(CogdoFlyingObstacle.EnterEventName, [self, collEntry])
def _handleExitCollision(self, collEntry):
messenger.send(CogdoFlyingObstacle.ExitEventName, [self, collEntry])
from pandac.PandaModules import TransformState
class CogdoFlyingWhirlwind(CogdoFlyingObstacle):
def __init__(self, index, model, motionPath = None):
collSolid = CollisionTube(0, 0, 0, 0, 0, Globals.Gameplay.WhirlwindCollisionTubeHeight, Globals.Gameplay.WhirlwindCollisionTubeRadius)
CogdoFlyingObstacle.__init__(self, Globals.Level.ObstacleTypes.Whirlwind, index, model, collSolid, motionPath=motionPath, motionPattern=CogdoFlyingObstacle.MotionTypes.BackForth)
self.t = 0.0
self._initModel()
def _initModel(self):
self.model.setDepthWrite(False)
self._texStage = self.model.findTextureStage('*')
self._soundIval = base.cogdoGameAudioMgr.createSfxIval('whirlwind', source=self.model)
self.model.setBin('transparent', self.index)
def startMoving(self, elapsedTime):
CogdoFlyingObstacle.startMoving(self, elapsedTime)
self.t = 0.0
self._soundIval.loop()
def update(self, dt):
self.t += dt
trans = TransformState.makePos((self.t, -self.t, 0))
self.model.setTexTransform(self._texStage, trans)
trans = TransformState.makePos((self.t * 2.0, -self.t * 2.0, 0))
def stopMoving(self):
CogdoFlyingObstacle.stopMoving(self)
self._soundIval.pause()
def destroy(self):
self._soundIval.clearToInitial()
del self._soundIval
CogdoFlyingObstacle.destroy(self)
class CogdoFlyingMinion(CogdoFlyingObstacle):
def __init__(self, index, collSolid, motionPath = None):
self.prop = None
self.suit = Suit.Suit()
d = SuitDNA.SuitDNA()
d.newSuit(Globals.Gameplay.MinionDnaName)
self.suit.setDNA(d)
self.suit.setScale(Globals.Gameplay.MinionScale)
self.suit.nametag3d.stash()
self.suit.nametag.destroy()
swapAvatarShadowPlacer(self.suit, 'minion-%sShadowPlacer' % index)
self.mopathNodePath = NodePath('mopathNodePath')
self.suit.reparentTo(self.mopathNodePath)
CogdoFlyingObstacle.__init__(self, Globals.Level.ObstacleTypes.Minion, index, self.mopathNodePath, collSolid, motionPath=motionPath, motionPattern=CogdoFlyingObstacle.MotionTypes.Loop, blendMotion=False, instanceModel=False)
self.lastPos = None
self.suit.loop('neutral')
return
def attachPropeller(self):
if self.prop is None:
self.prop = BattleProps.globalPropPool.getProp('propeller')
head = self.suit.find('**/joint_head')
self.prop.reparentTo(head)
return
def detachPropeller(self):
if self.prop:
self.prop.cleanup()
self.prop.removeNode()
self.prop = None
return
def startMoving(self, elapsedTime):
CogdoFlyingObstacle.startMoving(self, elapsedTime)
def stopMoving(self):
CogdoFlyingObstacle.stopMoving(self)
def update(self, dt):
CogdoFlyingObstacle.update(self, dt)
self.currPos = self.mopathNodePath.getPos()
if self.lastPos != None:
vec = self.currPos - self.lastPos
self.mopathNodePath.lookAt(self.currPos + vec)
self.mopathNodePath.setP(0)
self.lastPos = self.mopathNodePath.getPos()
return
def destroy(self):
self.mopathNodePath.removeNode()
del self.mopathNodePath
self.suit.cleanup()
self.suit.removeNode()
self.suit.delete()
CogdoFlyingObstacle.destroy(self)
class CogdoFlyingMinionFlying(CogdoFlyingMinion):
def __init__(self, index, motionPath = None):
radius = Globals.Gameplay.FlyingMinionCollisionRadius
offset = Globals.Gameplay.FlyingMinionCollisionHeightOffset
collSolid = CollisionSphere(0, 0, offset, radius)
CogdoFlyingMinion.__init__(self, index, collSolid, motionPath)
self.attachPropeller()
self.propTrack = Sequence(ActorInterval(self.prop, 'propeller', startFrame=0, endFrame=14))
dur = Globals.Gameplay.FlyingMinionFloatTime
offset = Globals.Gameplay.FlyingMinionFloatOffset
suitPos = self.suit.getPos()
upperPos = suitPos + Point3(0.0, 0.0, offset / 2.0)
lowerPos = suitPos + Point3(0.0, 0.0, -offset / 2.0)
self.floatSequence = Sequence(LerpPosInterval(self.suit, dur / 4.0, startPos=suitPos, pos=upperPos, blendType='easeInOut'), LerpPosInterval(self.suit, dur / 2.0, startPos=upperPos, pos=lowerPos, blendType='easeInOut'), LerpPosInterval(self.suit, dur / 4.0, startPos=lowerPos, pos=suitPos, blendType='easeInOut'), name='%s.floatSequence%i' % (self.__class__.__name__, self.index))
def startMoving(self, elapsedTime):
CogdoFlyingMinion.startMoving(self, elapsedTime)
self.floatSequence.loop(elapsedTime)
self.propTrack.loop(elapsedTime)
self.suit.pose('landing', 0)
def stopMoving(self):
CogdoFlyingMinion.stopMoving(self)
self.floatSequence.clearToInitial()
self.propTrack.pause()
def destroy(self):
self.floatSequence.clearToInitial()
del self.floatSequence
self.propTrack.clearToInitial()
del self.propTrack
CogdoFlyingMinion.destroy(self)
class CogdoFlyingMinionWalking(CogdoFlyingMinion):
def __init__(self, index, motionPath = None):
radius = Globals.Gameplay.WalkingMinionCollisionRadius
offset = Globals.Gameplay.WalkingMinionCollisionHeightOffset
collSolid = CollisionSphere(0, 0, offset, radius)
CogdoFlyingMinion.__init__(self, index, collSolid, motionPath)
def startMoving(self, elapsedTime):
CogdoFlyingMinion.startMoving(self, elapsedTime)
self.suit.loop('walk')
def stopMoving(self):
CogdoFlyingMinion.stopMoving(self)
self.suit.loop('neutral')
class CogdoFlyingFan(CogdoFlyingObstacle):
def __init__(self, index, model, motionPath = None):
collSolid = CollisionTube(0, 0, 0, 0, 0, Globals.Gameplay.FanCollisionTubeHeight, Globals.Gameplay.FanCollisionTubeRadius)
CogdoFlyingObstacle.__init__(self, Globals.Level.ObstacleTypes.Fan, index, model, collSolid)
self.streamers = self.model.findAllMatches('**/streamer*')
self._initIntervals()
def _initIntervals(self):
self.streamerIvals = []
minDur = Globals.Gameplay.FanStreamerMinDuration
maxDur = Globals.Gameplay.FanStreamerMaxDuration
for streamer in self.streamers:
dur = random.uniform(minDur, maxDur)
streamerLerp = LerpFunc(streamer.setH, fromData=0.0, toData=360.0, duration=dur, name='%s.streamerLerp%i-%s' % (self.__class__.__name__, self.index, streamer.getName()))
self.streamerIvals.append(streamerLerp)
def startMoving(self, elapsedTime = 0.0):
CogdoFlyingObstacle.startMoving(self, elapsedTime)
timeDelay = 0.0
maxDur = Globals.Gameplay.FanStreamerMaxDuration
for ival in self.streamerIvals:
taskName = 'delayedStreamerSpinTask-fan-%i-%s' % (self.index, ival.getName())
taskMgr.doMethodLater(timeDelay, ival.loop, taskName, extraArgs=[])
timeDelay += maxDur / (len(self.streamers) - 1)
def stopMoving(self):
CogdoFlyingObstacle.stopMoving(self)
taskMgr.removeTasksMatching('delayedStreamerSpinTask-fan-%i*' % self.index)
for streamerLerp in self.streamerIvals:
streamerLerp.pause()
def setBlowDirection(self):
tempNodePath = NodePath('temp')
tempNodePath.reparentTo(self.model)
tempNodePath.setPos(0, 0, 1)
self.blowVec = tempNodePath.getPos(render) - self.model.getPos(render)
self.blowVec.normalize()
tempNodePath.removeNode()
del tempNodePath
def getBlowDirection(self):
return Vec3(self.blowVec)
def destroy(self):
taskMgr.removeTasksMatching('delayedStreamerSpinTask-fan-%i*' % self.index)
for streamerLerp in self.streamerIvals:
streamerLerp.clearToInitial()
del self.streamerIvals[:]
CogdoFlyingObstacle.destroy(self)
del self.blowVec