301 lines
12 KiB
Python
301 lines
12 KiB
Python
|
from panda3d.core import *
|
||
|
from direct.interval.IntervalGlobal import *
|
||
|
from toontown.toonbase.ToontownGlobals import *
|
||
|
from CrateGlobals import *
|
||
|
from direct.showbase.PythonUtil import fitSrcAngle2Dest
|
||
|
from direct.distributed import DistributedObject
|
||
|
from direct.directnotify import DirectNotifyGlobal
|
||
|
import MovingPlatform
|
||
|
from direct.task.Task import Task
|
||
|
import DistributedCrushableEntity
|
||
|
|
||
|
class DistributedCrate(DistributedCrushableEntity.DistributedCrushableEntity):
|
||
|
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedCrate')
|
||
|
UP_KEY = 'arrow_up'
|
||
|
DOWN_KEY = 'arrow_down'
|
||
|
LEFT_KEY = 'arrow_left'
|
||
|
RIGHT_KEY = 'arrow_right'
|
||
|
ModelPaths = ('phase_9/models/cogHQ/woodCrateB', 'phase_10/models/cashbotHQ/CBWoodCrate')
|
||
|
|
||
|
def __init__(self, cr):
|
||
|
DistributedCrushableEntity.DistributedCrushableEntity.__init__(self, cr)
|
||
|
self.initNodePath()
|
||
|
self.modelType = 0
|
||
|
self.crate = None
|
||
|
self.gridSize = 3.0
|
||
|
self.tContact = 0
|
||
|
self.tStick = 0.01
|
||
|
self.moveTrack = None
|
||
|
self.avMoveTrack = None
|
||
|
self.avPushTrack = None
|
||
|
self.crate = None
|
||
|
self.crushTrack = None
|
||
|
self.isLocalToon = 0
|
||
|
self.stuckToCrate = 0
|
||
|
self.upPressed = 0
|
||
|
self.isPushing = 0
|
||
|
self.creakSound = loader.loadSfx('phase_9/audio/sfx/CHQ_FACT_crate_effort.ogg')
|
||
|
self.pushSound = loader.loadSfx('phase_9/audio/sfx/CHQ_FACT_crate_sliding.ogg')
|
||
|
return
|
||
|
|
||
|
def disable(self):
|
||
|
self.ignoreAll()
|
||
|
if self.moveTrack:
|
||
|
self.moveTrack.pause()
|
||
|
del self.moveTrack
|
||
|
if self.avMoveTrack:
|
||
|
self.avMoveTrack.pause()
|
||
|
del self.avMoveTrack
|
||
|
if self.avPushTrack:
|
||
|
self.avPushTrack.pause()
|
||
|
del self.avPushTrack
|
||
|
if self.crate:
|
||
|
self.crate.destroy()
|
||
|
del self.crate
|
||
|
if self.crushTrack:
|
||
|
self.crushTrack.pause()
|
||
|
del self.crushTrack
|
||
|
taskMgr.remove(self.taskName('crushTask'))
|
||
|
if self.pushable:
|
||
|
self.__listenForCollisions(0)
|
||
|
self.ignore('arrow_up')
|
||
|
self.ignore('arrow_up-up')
|
||
|
DistributedCrushableEntity.DistributedCrushableEntity.disable(self)
|
||
|
|
||
|
def delete(self):
|
||
|
DistributedCrushableEntity.DistributedCrushableEntity.delete(self)
|
||
|
del self.creakSound
|
||
|
del self.pushSound
|
||
|
|
||
|
def generateInit(self):
|
||
|
DistributedCrushableEntity.DistributedCrushableEntity.generateInit(self)
|
||
|
|
||
|
def generate(self):
|
||
|
DistributedCrushableEntity.DistributedCrushableEntity.generate(self)
|
||
|
|
||
|
def announceGenerate(self):
|
||
|
self.notify.debug('announceGenerate')
|
||
|
DistributedCrushableEntity.DistributedCrushableEntity.announceGenerate(self)
|
||
|
self.loadModel()
|
||
|
self.modCrateCollisions()
|
||
|
if self.pushable:
|
||
|
self.__listenForCollisions(1)
|
||
|
self.accept('arrow_up', self.__upKeyPressed)
|
||
|
|
||
|
def modCrateCollisions(self):
|
||
|
cNode = self.find('**/wall')
|
||
|
cNode.setName(self.uniqueName('crateCollision'))
|
||
|
cNode.setZ(-.8)
|
||
|
colNode = self.find('**/collision')
|
||
|
floor = colNode.find('**/MovingPlatform*')
|
||
|
floor2 = floor.copyTo(colNode)
|
||
|
floor2.setZ(-.8)
|
||
|
|
||
|
def __upKeyPressed(self):
|
||
|
self.ignore('arrow_up')
|
||
|
self.accept('arrow_up-up', self.__upKeyReleased)
|
||
|
self.upPressed = 1
|
||
|
|
||
|
def __upKeyReleased(self):
|
||
|
self.ignore('arrow_up-up')
|
||
|
self.accept('arrow_up', self.__upKeyPressed)
|
||
|
self.upPressed = 0
|
||
|
if self.stuckToCrate:
|
||
|
self.__resetStick()
|
||
|
|
||
|
def loadModel(self):
|
||
|
crateModel = loader.loadModel(DistributedCrate.ModelPaths[self.modelType])
|
||
|
self.crate = MovingPlatform.MovingPlatform()
|
||
|
self.crate.setupCopyModel(self.getParentToken(), crateModel, 'floor')
|
||
|
self.setScale(1.0)
|
||
|
self.crate.setScale(self.scale)
|
||
|
self.crate.reparentTo(self)
|
||
|
self.crate.flattenLight()
|
||
|
|
||
|
def setScale(self, scale):
|
||
|
if self.crate:
|
||
|
self.crate.setScale(scale)
|
||
|
|
||
|
def __listenForCollisions(self, on):
|
||
|
if on:
|
||
|
self.accept(self.uniqueName('entercrateCollision'), self.handleCollision)
|
||
|
else:
|
||
|
self.ignore(self.uniqueName('entercrateCollision'))
|
||
|
|
||
|
def setPosition(self, x, y, z):
|
||
|
self.setPos(x, y, z)
|
||
|
|
||
|
def handleCollision(self, collEntry = None):
|
||
|
if not self.upPressed:
|
||
|
return
|
||
|
crateNormal = Vec3(collEntry.getSurfaceNormal(self))
|
||
|
relativeVec = base.localAvatar.getRelativeVector(self, crateNormal)
|
||
|
relativeVec.normalize()
|
||
|
worldVec = render.getRelativeVector(self, crateNormal)
|
||
|
worldVec.normalize()
|
||
|
offsetVec = Vec3(base.localAvatar.getPos(render) - self.getPos(render))
|
||
|
offsetVec.normalize()
|
||
|
offsetDot = offsetVec[0] * worldVec[0] + offsetVec[1] * worldVec[1]
|
||
|
self.notify.debug('offsetDot = %s, world = %s, rel = %s' % (offsetDot, worldVec, offsetVec))
|
||
|
if relativeVec.getY() < -0.7 and offsetDot > 0.9 and offsetVec.getZ() < 0.05:
|
||
|
self.getCrateSide(crateNormal)
|
||
|
self.tContact = globalClock.getFrameTime()
|
||
|
self.__listenForCollisions(0)
|
||
|
self.__listenForCancelEvents(1)
|
||
|
self.__startStickTask(crateNormal, base.localAvatar.getPos(render))
|
||
|
|
||
|
def setReject(self):
|
||
|
self.notify.debug('setReject')
|
||
|
self.sentRequest = 0
|
||
|
if self.stuckToCrate:
|
||
|
self.__resetStick()
|
||
|
|
||
|
def __startStickTask(self, crateNormal, toonPos):
|
||
|
self.__killStickTask()
|
||
|
self.stuckToCrate = 1
|
||
|
sTask = Task(self.__stickTask)
|
||
|
sTask.crateNormal = crateNormal
|
||
|
sTask.toonPos = toonPos
|
||
|
taskMgr.add(sTask, self.taskName('stickTask'))
|
||
|
|
||
|
def __killStickTask(self):
|
||
|
taskMgr.remove(self.taskName('stickTask'))
|
||
|
|
||
|
def __stickTask(self, task):
|
||
|
tElapsed = globalClock.getFrameTime() - self.tContact
|
||
|
if tElapsed > self.tStick:
|
||
|
lToon = base.localAvatar
|
||
|
self.isLocalToon = 1
|
||
|
crateNormal = task.crateNormal
|
||
|
crateWidth = 2.75 * self.scale
|
||
|
offset = crateWidth + 1.5 + TorsoToOffset[lToon.style.torso]
|
||
|
newPos = crateNormal * offset
|
||
|
if self.avPushTrack:
|
||
|
self.avPushTrack.pause()
|
||
|
place = base.cr.playGame.getPlace()
|
||
|
newHpr = CrateHprs[self.crateSide]
|
||
|
h = lToon.getH(self)
|
||
|
h = fitSrcAngle2Dest(h, newHpr[0])
|
||
|
startHpr = Vec3(h, 0, 0)
|
||
|
self.avPushTrack = Sequence(LerpPosHprInterval(lToon, 0.25, newPos, newHpr, startHpr=startHpr, other=self, blendType='easeInOut'), Func(place.fsm.request, 'push'), Func(self.__sendPushRequest, task.crateNormal), SoundInterval(self.creakSound, node=self))
|
||
|
self.avPushTrack.start()
|
||
|
return Task.done
|
||
|
else:
|
||
|
pos = task.toonPos
|
||
|
base.localAvatar.setPos(task.toonPos)
|
||
|
return Task.cont
|
||
|
|
||
|
def getCrateSide(self, crateNormal):
|
||
|
for i in xrange(len(CrateNormals)):
|
||
|
dotP = CrateNormals[i].dot(crateNormal)
|
||
|
if dotP > 0.9:
|
||
|
self.crateSide = i
|
||
|
|
||
|
def __sendPushRequest(self, crateNormal):
|
||
|
self.notify.debug('__sendPushRequest')
|
||
|
if self.crateSide != None:
|
||
|
self.sentRequest = 1
|
||
|
self.sendUpdate('requestPush', [self.crateSide])
|
||
|
else:
|
||
|
self.notify.debug("didn't send request")
|
||
|
return
|
||
|
|
||
|
def __listenForCancelEvents(self, on):
|
||
|
self.notify.debug('%s, __listenForCancelEvents(%s)' % (self.doId, on))
|
||
|
if on:
|
||
|
self.accept('arrow_down', self.__resetStick)
|
||
|
self.accept('arrow_left', self.__resetStick)
|
||
|
self.accept('arrow_right', self.__resetStick)
|
||
|
else:
|
||
|
self.ignore('arrow_down')
|
||
|
self.ignore('arrow_left')
|
||
|
self.ignore('arrow_right')
|
||
|
|
||
|
def setMoveTo(self, avId, x0, y0, z0, x1, y1, z1):
|
||
|
self.notify.debug('setMoveTo')
|
||
|
self.__moveCrateTo(Vec3(x0, y0, z0), Vec3(x1, y1, z1))
|
||
|
isLocal = base.localAvatar.doId == avId
|
||
|
if isLocal and self.stuckToCrate or not isLocal:
|
||
|
self.__moveAvTo(avId, Vec3(x0, y0, z0), Vec3(x1, y1, z1))
|
||
|
|
||
|
def __moveCrateTo(self, startPos, endPos):
|
||
|
if self.moveTrack:
|
||
|
self.moveTrack.finish()
|
||
|
self.moveTrack = None
|
||
|
self.moveTrack = Parallel(Sequence(LerpPosInterval(self, T_PUSH, endPos, startPos=startPos, fluid=1)), SoundInterval(self.creakSound, node=self), SoundInterval(self.pushSound, node=self, duration=T_PUSH, volume=0.2))
|
||
|
self.moveTrack.start()
|
||
|
return
|
||
|
|
||
|
def __moveAvTo(self, avId, startPos, endPos):
|
||
|
if self.avMoveTrack:
|
||
|
self.avMoveTrack.finish()
|
||
|
self.avMoveTrack = None
|
||
|
av = base.cr.doId2do.get(avId)
|
||
|
if av:
|
||
|
avMoveTrack = Sequence()
|
||
|
moveDir = endPos - startPos
|
||
|
crateNormal = startPos - endPos
|
||
|
crateNormal.normalize()
|
||
|
crateWidth = 2.75 * self.scale
|
||
|
offset = crateWidth + 1.5 + TorsoToOffset[av.style.torso]
|
||
|
toonOffset = crateNormal * offset
|
||
|
avMoveTrack.append(Sequence(LerpPosInterval(av, T_PUSH, toonOffset, startPos=toonOffset, other=self)))
|
||
|
self.avMoveTrack = avMoveTrack
|
||
|
self.avMoveTrack.start()
|
||
|
return
|
||
|
|
||
|
def __resetStick(self):
|
||
|
self.notify.debug('__resetStick')
|
||
|
self.__killStickTask()
|
||
|
self.__listenForCancelEvents(0)
|
||
|
self.__listenForCollisions(1)
|
||
|
self.sendUpdate('setDone')
|
||
|
if self.avPushTrack:
|
||
|
self.avPushTrack.pause()
|
||
|
del self.avPushTrack
|
||
|
self.avPushTrack = None
|
||
|
if self.avMoveTrack:
|
||
|
self.avMoveTrack.pause()
|
||
|
del self.avMoveTrack
|
||
|
self.avMoveTrack = None
|
||
|
base.cr.playGame.getPlace().fsm.request('walk')
|
||
|
self.crateSide = None
|
||
|
self.crateNormal = None
|
||
|
self.isLocalToon = 0
|
||
|
self.stuckToCrate = 0
|
||
|
return
|
||
|
|
||
|
def playCrushMovie(self, crusherId, axis):
|
||
|
self.notify.debug('playCrushMovie')
|
||
|
taskMgr.remove(self.taskName('crushTask'))
|
||
|
taskMgr.add(self.crushTask, self.taskName('crushTask'), extraArgs=(crusherId, axis), priority=25)
|
||
|
|
||
|
def crushTask(self, crusherId, axis):
|
||
|
crusher = self.level.entities.get(crusherId, None)
|
||
|
if crusher:
|
||
|
crusherHeight = crusher.model.getPos(self)[2]
|
||
|
maxHeight = self.pos[2] + self.scale
|
||
|
minHeight = crusher.getPos(self)[2]
|
||
|
minScale = minHeight / maxHeight
|
||
|
self.notify.debug('cHeight= %s' % crusherHeight)
|
||
|
if crusherHeight < maxHeight and crusherHeight >= minHeight:
|
||
|
if crusherHeight == minHeight:
|
||
|
self.setScale(Vec3(1.2, 1.2, minScale))
|
||
|
taskMgr.doMethodLater(2, self.setScale, 'resetScale', extraArgs=(1,))
|
||
|
return Task.done
|
||
|
else:
|
||
|
k = crusherHeight / maxHeight
|
||
|
sx = min(1 / k, 0.2)
|
||
|
self.setScale(Vec3(1 + sx, 1 + sx, k))
|
||
|
return Task.cont
|
||
|
|
||
|
def originalTry(self, axis):
|
||
|
tSquash = 0.4
|
||
|
if self.crushTrack:
|
||
|
self.crushTrack.finish()
|
||
|
del self.crushTrack
|
||
|
self.crushTrack = None
|
||
|
self.crushTrack = Sequence(LerpScaleInterval(self, tSquash, VBase3(1.2, 1.2, 0.25), blendType='easeInOut'), LerpColorScaleInterval(self, 2.0, VBase4(1, 1, 1, 0), blendType='easeInOut'), Wait(2.0), LerpScaleInterval(self, 0.1, VBase3(1, 1, 1), blendType='easeInOut'), LerpColorScaleInterval(self, 0.1, VBase4(1, 1, 1, 0), blendType='easeInOut'))
|
||
|
self.crushTrack.start()
|
||
|
return
|