oldschool-toontown/toontown/coghq/DistributedLawbotCannon.py

877 lines
34 KiB
Python
Raw Permalink Normal View History

2019-11-02 17:27:54 -05:00
from direct.interval.IntervalGlobal import *
from direct.distributed.ClockDelta import *
from direct.task.Task import Task
from direct.distributed import DistributedObject
from direct.directnotify import DirectNotifyGlobal
from panda3d.core import CollisionSphere, CollisionNode
2019-11-02 17:27:54 -05:00
from toontown.toonbase import ToontownGlobals
from toontown.estate import DistributedCannon
from toontown.estate import CannonGlobals
from direct.gui.DirectGui import *
from panda3d.core import *
from panda3d.otp import *
2019-11-02 17:27:54 -05:00
from toontown.toon import NPCToons
from toontown.toon import ToonHead
from toontown.toonbase import TTLocalizer
from toontown.minigame import Trajectory
from toontown.effects import DustCloud
GROUND_PLANE_MIN = -15
CANNON_ROTATION_MIN = -55
CANNON_ROTATION_MAX = 50
CANNON_ROTATION_VEL = 15.0
CANNON_ANGLE_MIN = 10
CANNON_ANGLE_MAX = 85
CANNON_ANGLE_VEL = 15.0
INITIAL_VELOCITY = 80
CANNON_MOVE_UPDATE_FREQ = 0.5
CAMERA_PULLBACK_MIN = 20
CAMERA_PULLBACK_MAX = 40
class DistributedLawbotCannon(DistributedObject.DistributedObject):
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedLawbotCannon')
LOCAL_CANNON_MOVE_TASK = 'localCannonMoveTask'
FIRE_KEY = 'control'
UP_KEY = 'arrow_up'
DOWN_KEY = 'arrow_down'
LEFT_KEY = 'arrow_left'
RIGHT_KEY = 'arrow_right'
HIT_GROUND = 0
def __init__(self, cr):
DistributedObject.DistributedObject.__init__(self, cr)
self.index = None
self.avId = 0
self.av = None
self.localToonShooting = 0
self.cannonsActive = 0
self.cannonLocation = None
self.cannonPostion = None
self.cannon = None
self.madeGui = 0
self.jurorToon = None
self.toonModel = None
self.toonHead = None
self.toonScale = None
self.dustCloud = None
self.hitBumper = 0
self.hitTarget = 0
self.lastPos = Vec3(0, 0, 0)
self.lastVel = Vec3(0, 0, 0)
self.vel = Vec3(0, 0, 0)
self.landingPos = Vec3(0, 0, 0)
self.t = 0
self.lastT = 0
self.deltaT = 0
self.hitTrack = None
self.flyColNode = None
self.flyColNodePath = None
self.localAvId = base.localAvatar.doId
self.model_Created = 0
return
def disable(self):
taskMgr.remove(self.uniqueName('fireCannon'))
taskMgr.remove(self.uniqueName('shootTask'))
self.__stopFlyTask(self.avId)
taskMgr.remove(self.uniqueName('flyTask'))
self.ignoreAll()
self.setMovie(CannonGlobals.CANNON_MOVIE_CLEAR, 0, 0)
self.nodePath.detachNode()
self.__unmakeGui()
if self.hitTrack:
self.hitTrack.finish()
del self.hitTrack
self.hitTrack = None
DistributedObject.DistributedObject.disable(self)
return
def delete(self):
self.offstage()
self.unload()
DistributedObject.DistributedObject.delete(self)
def announceGenerate(self):
DistributedObject.DistributedObject.announceGenerate(self)
self.boss.cannons[self.index] = self
def generateInit(self):
DistributedObject.DistributedObject.generateInit(self)
self.nodePath = NodePath(self.uniqueName('Cannon'))
self.load()
self.activateCannons()
def setPosHpr(self, x, y, z, h, p, r):
self.nodePath.setPosHpr(x, y, z, h, p, r)
def setBossCogId(self, bossCogId):
self.bossCogId = bossCogId
self.boss = base.cr.doId2do[bossCogId]
def getSphereRadius(self):
return 1.5
def getParentNodePath(self):
return render
def setIndex(self, index):
self.index = index
def load(self):
self.cannon = loader.loadModel('phase_4/models/minigames/toon_cannon')
self.collSphere = CollisionSphere(0, 0, 0, self.getSphereRadius())
self.dustCloud = DustCloud.DustCloud(render)
self.dustCloud.setBillboardPointEye()
self.collSphere.setTangible(1)
self.collNode = CollisionNode(self.uniqueName('CannonSphere'))
self.collNode.setCollideMask(ToontownGlobals.WallBitmask)
self.collNode.addSolid(self.collSphere)
self.collNodePath = self.nodePath.attachNewNode(self.collNode)
self.cannon.reparentTo(self.nodePath)
self.kartColNode = CollisionNode(self.uniqueName('KartColNode'))
self.kartNode = self.nodePath.attachNewNode(self.kartColNode)
2020-01-14 13:28:52 -06:00
self.sndCannonMove = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_adjust.ogg')
self.sndCannonFire = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_fire_alt.ogg')
self.sndHitGround = base.loader.loadSfx('phase_4/audio/sfx/MG_cannon_hit_dirt.ogg')
self.sndHitChair = base.loader.loadSfx('phase_11/audio/sfx/LB_toon_jury.ogg')
2019-11-02 17:27:54 -05:00
self.cannon.hide()
self.flashingLabel = None
return
def unload(self):
if self.cannon:
self.cannon.removeNode()
del self.cannon
if self.dustCloud != None:
self.dustCloud.destroy()
del self.dustCloud
del self.sndCannonMove
del self.sndCannonFire
del self.sndHitGround
del self.sndHitChair
if self.av:
self.__resetToon(self.av)
self.av.loop('neutral')
self.av.setPlayRate(1.0, 'run')
if self.toonHead != None:
self.toonHead.stopBlink()
self.toonHead.stopLookAroundNow()
self.toonHead.delete()
del self.toonHead
if self.toonModel != None:
self.toonModel.removeNode()
del self.toonModel
if self.jurorToon != None:
self.jurorToon.delete()
del self.jurorToon
del self.toonScale
return
def activateCannons(self):
if not self.cannonsActive:
self.cannonsActive = 1
self.onstage()
self.nodePath.reparentTo(self.getParentNodePath())
self.accept(self.uniqueName('enterCannonSphere'), self.__handleEnterSphere)
def onstage(self):
self.__createCannon()
self.cannon.reparentTo(self.nodePath)
self.dustCloud.reparentTo(render)
def offstage(self):
if self.cannon:
self.cannon.reparentTo(hidden)
if self.dustCloud:
self.dustCloud.reparentTo(hidden)
self.dustCloud.stop()
def __createCannon(self):
self.barrel = self.cannon.find('**/cannon')
self.cannonLocation = Point3(0, 0, 0.025)
self.cannonPosition = [0, CANNON_ANGLE_MIN]
self.cannon.setPos(self.cannonLocation)
self.__updateCannonPosition(self.avId)
def updateCannonPosition(self, avId, zRot, angle):
if avId != self.localAvId:
self.cannonPosition = [zRot, angle]
self.__updateCannonPosition(avId)
def __updateCannonPosition(self, avId):
self.cannon.setHpr(self.cannonPosition[0], 0.0, 0.0)
self.barrel.setHpr(0.0, self.cannonPosition[1], 0.0)
maxP = 90
newP = self.barrel.getP()
yScale = 1 - 0.5 * float(newP) / maxP
shadow = self.cannon.find('**/square_drop_shadow')
shadow.setScale(1, yScale, 1)
def __handleEnterSphere(self, collEntry):
self.d_requestEnter()
def d_requestEnter(self):
self.sendUpdate('requestEnter', [])
def setMovie(self, mode, avId, extraInfo):
wasLocalToon = self.localToonShooting
self.avId = avId
if mode == CannonGlobals.CANNON_MOVIE_CLEAR:
self.setLanded()
elif mode == CannonGlobals.CANNON_MOVIE_LANDED:
self.setLanded()
elif mode == CannonGlobals.CANNON_MOVIE_FORCE_EXIT:
self.exitCannon(self.avId)
self.setLanded()
elif mode == CannonGlobals.CANNON_MOVIE_LOAD:
if self.avId == base.localAvatar.doId:
self.cannonBallsLeft = extraInfo
base.cr.playGame.getPlace().setState('crane')
base.localAvatar.setTeleportAvailable(0)
self.localToonShooting = 1
self.__makeGui()
camera.reparentTo(self.barrel)
camera.setPos(0.5, -2, 2.5)
camera.setHpr(0, 0, 0)
self.boss.toonEnteredCannon(self.avId, self.index)
if self.avId in self.cr.doId2do:
2019-11-02 17:27:54 -05:00
self.av = self.cr.doId2do[self.avId]
self.acceptOnce(self.av.uniqueName('disable'), self.__avatarGone)
self.av.loop('neutral')
self.av.stopSmooth()
self.__destroyToonModels()
self.__createToonModels()
self.av.setPosHpr(3, 0, 0, 90, 0, 0)
self.av.reparentTo(self.cannon)
else:
self.notify.warning('Unknown avatar %d in cannon %d' % (self.avId, self.doId))
else:
self.notify.warning('unhandled case, mode = %d' % mode)
def __avatarGone(self):
self.setMovie(CannonGlobals.CANNON_MOVIE_CLEAR, 0, 0)
def __makeGui(self):
if self.madeGui:
return
NametagGlobals.setMasterArrowsOn(0)
guiModel = 'phase_4/models/gui/cannon_game_gui'
cannonGui = loader.loadModel(guiModel)
self.aimPad = DirectFrame(image=cannonGui.find('**/CannonFire_PAD'), relief=None, pos=(0.7, 0, -0.553333), scale=0.8)
cannonGui.removeNode()
self.fireButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Fire_Btn_UP'), (guiModel, '**/Fire_Btn_DN'), (guiModel, '**/Fire_Btn_RLVR')), relief=None, pos=(0.0115741, 0, 0.00505051), scale=1.0, command=self.__firePressed)
self.upButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Cannon_Arrow_UP'), (guiModel, '**/Cannon_Arrow_DN'), (guiModel, '**/Cannon_Arrow_RLVR')), relief=None, pos=(0.0115741, 0, 0.221717))
self.downButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Cannon_Arrow_UP'), (guiModel, '**/Cannon_Arrow_DN'), (guiModel, '**/Cannon_Arrow_RLVR')), relief=None, pos=(0.0136112, 0, -0.210101), image_hpr=(0, 0, 180))
self.leftButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Cannon_Arrow_UP'), (guiModel, '**/Cannon_Arrow_DN'), (guiModel, '**/Cannon_Arrow_RLVR')), relief=None, pos=(-0.199352, 0, -0.000505269), image_hpr=(0, 0, -90))
self.rightButton = DirectButton(parent=self.aimPad, image=((guiModel, '**/Cannon_Arrow_UP'), (guiModel, '**/Cannon_Arrow_DN'), (guiModel, '**/Cannon_Arrow_RLVR')), relief=None, pos=(0.219167, 0, -0.00101024), image_hpr=(0, 0, 90))
guiClose = loader.loadModel('phase_3.5/models/gui/avatar_panel_gui')
cannonBallText = '%d/%d' % (self.cannonBallsLeft, ToontownGlobals.LawbotBossCannonBallMax)
self.cannonBallLabel = DirectLabel(parent=self.aimPad, text=cannonBallText, text_fg=VBase4(1, 1, 1, 1), text_align=TextNode.ACenter, relief=None, pos=(0.475, 0.0, -0.35), scale=0.25)
if self.cannonBallsLeft < 5:
if self.flashingLabel:
self.flashingLabel.stop()
flashingTrack = Sequence()
for i in range(10):
flashingTrack.append(LerpColorScaleInterval(self.cannonBallLabel, 0.5, VBase4(1, 0, 0, 1)))
flashingTrack.append(LerpColorScaleInterval(self.cannonBallLabel, 0.5, VBase4(1, 1, 1, 1)))
self.flashingLabel = flashingTrack
self.flashingLabel.start()
self.aimPad.setColor(1, 1, 1, 0.9)
def bindButton(button, upHandler, downHandler):
button.bind(DGG.B1PRESS, lambda x, handler = upHandler: handler())
button.bind(DGG.B1RELEASE, lambda x, handler = downHandler: handler())
bindButton(self.upButton, self.__upPressed, self.__upReleased)
bindButton(self.downButton, self.__downPressed, self.__downReleased)
bindButton(self.leftButton, self.__leftPressed, self.__leftReleased)
bindButton(self.rightButton, self.__rightPressed, self.__rightReleased)
self.__enableAimInterface()
self.madeGui = 1
return
def __unmakeGui(self):
self.notify.debug('__unmakeGui')
if not self.madeGui:
return
if self.flashingLabel:
self.flashingLabel.finish()
self.flashingLabel = None
NametagGlobals.setMasterArrowsOn(1)
self.__disableAimInterface()
self.upButton.unbind(DGG.B1PRESS)
self.upButton.unbind(DGG.B1RELEASE)
self.downButton.unbind(DGG.B1PRESS)
self.downButton.unbind(DGG.B1RELEASE)
self.leftButton.unbind(DGG.B1PRESS)
self.leftButton.unbind(DGG.B1RELEASE)
self.rightButton.unbind(DGG.B1PRESS)
self.rightButton.unbind(DGG.B1RELEASE)
self.aimPad.destroy()
del self.aimPad
del self.fireButton
del self.upButton
del self.downButton
del self.leftButton
del self.rightButton
self.madeGui = 0
return
def __enableAimInterface(self):
self.aimPad.show()
self.accept(self.FIRE_KEY, self.__fireKeyPressed)
self.accept(self.UP_KEY, self.__upKeyPressed)
self.accept(self.DOWN_KEY, self.__downKeyPressed)
self.accept(self.LEFT_KEY, self.__leftKeyPressed)
self.accept(self.RIGHT_KEY, self.__rightKeyPressed)
self.__spawnLocalCannonMoveTask()
def __disableAimInterface(self):
self.aimPad.hide()
self.ignore(self.FIRE_KEY)
self.ignore(self.UP_KEY)
self.ignore(self.DOWN_KEY)
self.ignore(self.LEFT_KEY)
self.ignore(self.RIGHT_KEY)
self.ignore(self.FIRE_KEY + '-up')
self.ignore(self.UP_KEY + '-up')
self.ignore(self.DOWN_KEY + '-up')
self.ignore(self.LEFT_KEY + '-up')
self.ignore(self.RIGHT_KEY + '-up')
self.__killLocalCannonMoveTask()
def __fireKeyPressed(self):
self.ignore(self.FIRE_KEY)
self.accept(self.FIRE_KEY + '-up', self.__fireKeyReleased)
self.__firePressed()
def __upKeyPressed(self):
self.ignore(self.UP_KEY)
self.accept(self.UP_KEY + '-up', self.__upKeyReleased)
self.__upPressed()
def __downKeyPressed(self):
self.ignore(self.DOWN_KEY)
self.accept(self.DOWN_KEY + '-up', self.__downKeyReleased)
self.__downPressed()
def __leftKeyPressed(self):
self.ignore(self.LEFT_KEY)
self.accept(self.LEFT_KEY + '-up', self.__leftKeyReleased)
self.__leftPressed()
def __rightKeyPressed(self):
self.ignore(self.RIGHT_KEY)
self.accept(self.RIGHT_KEY + '-up', self.__rightKeyReleased)
self.__rightPressed()
def __fireKeyReleased(self):
self.ignore(self.FIRE_KEY + '-up')
self.accept(self.FIRE_KEY, self.__fireKeyPressed)
def __leftKeyReleased(self):
self.ignore(self.LEFT_KEY + '-up')
self.accept(self.LEFT_KEY, self.__leftKeyPressed)
self.__leftReleased()
def __rightKeyReleased(self):
self.ignore(self.RIGHT_KEY + '-up')
self.accept(self.RIGHT_KEY, self.__rightKeyPressed)
self.__rightReleased()
def __upKeyReleased(self):
self.ignore(self.UP_KEY + '-up')
self.accept(self.UP_KEY, self.__upKeyPressed)
self.__upReleased()
def __downKeyReleased(self):
self.ignore(self.DOWN_KEY + '-up')
self.accept(self.DOWN_KEY, self.__downKeyPressed)
self.__downReleased()
def __leaveCannon(self):
self.notify.debug('__leaveCannon')
self.sendUpdate('requestLeave')
def __firePressed(self):
self.notify.debug('fire pressed')
if not self.boss.state == 'BattleTwo':
self.notify.debug('boss is in state=%s, not firing' % self.boss.state)
return
self.__broadcastLocalCannonPosition()
self.__unmakeGui()
self.sendUpdate('setCannonLit', [self.cannonPosition[0], self.cannonPosition[1]])
def __upPressed(self):
self.notify.debug('up pressed')
self.upPressed = self.__enterControlActive(self.upPressed)
def __downPressed(self):
self.notify.debug('down pressed')
self.downPressed = self.__enterControlActive(self.downPressed)
def __leftPressed(self):
self.notify.debug('left pressed')
self.leftPressed = self.__enterControlActive(self.leftPressed)
def __rightPressed(self):
self.notify.debug('right pressed')
self.rightPressed = self.__enterControlActive(self.rightPressed)
def __upReleased(self):
self.notify.debug('up released')
self.upPressed = self.__exitControlActive(self.upPressed)
def __downReleased(self):
self.notify.debug('down released')
self.downPressed = self.__exitControlActive(self.downPressed)
def __leftReleased(self):
self.notify.debug('left released')
self.leftPressed = self.__exitControlActive(self.leftPressed)
def __rightReleased(self):
self.notify.debug('right released')
self.rightPressed = self.__exitControlActive(self.rightPressed)
def __enterControlActive(self, control):
return control + 1
def __exitControlActive(self, control):
return max(0, control - 1)
def __spawnLocalCannonMoveTask(self):
self.leftPressed = 0
self.rightPressed = 0
self.upPressed = 0
self.downPressed = 0
self.cannonMoving = 0
task = Task(self.__localCannonMoveTask)
task.lastPositionBroadcastTime = 0.0
taskMgr.add(task, self.LOCAL_CANNON_MOVE_TASK)
def __killLocalCannonMoveTask(self):
taskMgr.remove(self.LOCAL_CANNON_MOVE_TASK)
if self.cannonMoving:
self.sndCannonMove.stop()
def __localCannonMoveTask(self, task):
pos = self.cannonPosition
oldRot = pos[0]
oldAng = pos[1]
rotVel = 0
if self.leftPressed:
rotVel += CANNON_ROTATION_VEL
if self.rightPressed:
rotVel -= CANNON_ROTATION_VEL
pos[0] += rotVel * globalClock.getDt()
if pos[0] < CANNON_ROTATION_MIN:
pos[0] = CANNON_ROTATION_MIN
elif pos[0] > CANNON_ROTATION_MAX:
pos[0] = CANNON_ROTATION_MAX
angVel = 0
if self.upPressed:
angVel += CANNON_ANGLE_VEL
if self.downPressed:
angVel -= CANNON_ANGLE_VEL
pos[1] += angVel * globalClock.getDt()
if pos[1] < CANNON_ANGLE_MIN:
pos[1] = CANNON_ANGLE_MIN
elif pos[1] > CANNON_ANGLE_MAX:
pos[1] = CANNON_ANGLE_MAX
if oldRot != pos[0] or oldAng != pos[1]:
if self.cannonMoving == 0:
self.cannonMoving = 1
base.playSfx(self.sndCannonMove, looping=1)
self.__updateCannonPosition(self.localAvId)
if task.time - task.lastPositionBroadcastTime > CANNON_MOVE_UPDATE_FREQ:
task.lastPositionBroadcastTime = task.time
self.__broadcastLocalCannonPosition()
elif self.cannonMoving:
self.cannonMoving = 0
self.sndCannonMove.stop()
self.__broadcastLocalCannonPosition()
return Task.cont
def __broadcastLocalCannonPosition(self):
self.sendUpdate('setCannonPosition', [self.cannonPosition[0], self.cannonPosition[1]])
def __updateCannonPosition(self, avId):
self.cannon.setHpr(self.cannonPosition[0], 0.0, 0.0)
self.barrel.setHpr(0.0, self.cannonPosition[1], 0.0)
maxP = 90
newP = self.barrel.getP()
yScale = 1 - 0.5 * float(newP) / maxP
shadow = self.cannon.find('**/square_drop_shadow')
shadow.setScale(1, yScale, 1)
def __createToonModels(self):
self.model_Created = 1
self.jurorToon = NPCToons.createLocalNPC(ToontownGlobals.LawbotBossBaseJurorNpcId + self.index)
self.toonScale = self.jurorToon.getScale()
jurorToonParent = render.attachNewNode('toonOriginChange')
self.jurorToon.wrtReparentTo(jurorToonParent)
self.jurorToon.setPosHpr(0, 0, -(self.jurorToon.getHeight() / 2.0), 0, -90, 0)
self.toonModel = jurorToonParent
self.toonHead = ToonHead.ToonHead()
self.toonHead.setupHead(self.jurorToon.style)
self.toonHead.reparentTo(hidden)
self.__loadToonInCannon()
def __destroyToonModels(self):
if (0):
self.av.dropShadow.show()
if self.dropShadow != None:
self.dropShadow.removeNode()
self.dropShadow = None
self.hitBumper = 0
self.hitTarget = 0
self.angularVel = 0
self.vel = Vec3(0, 0, 0)
self.lastVel = Vec3(0, 0, 0)
self.lastPos = Vec3(0, 0, 0)
self.landingPos = Vec3(0, 0, 0)
self.t = 0
self.lastT = 0
self.deltaT = 0
self.av = None
self.lastWakeTime = 0
self.localToonShooting = 0
if self.toonHead != None:
self.toonHead.reparentTo(hidden)
self.toonHead.stopBlink()
self.toonHead.stopLookAroundNow()
self.toonHead = None
if self.toonModel != None:
self.toonModel.removeNode()
self.toonModel = None
if self.jurorToon != None:
self.jurorToon.delete()
self.jurorToon = None
self.model_Created = 0
return
def __loadToonInCannon(self):
self.toonModel.reparentTo(hidden)
self.toonHead.startBlink()
self.toonHead.startLookAround()
self.toonHead.reparentTo(self.barrel)
self.toonHead.setPosHpr(0, 6, 0, 0, -45, 0)
sc = self.toonScale
self.toonHead.setScale(render, sc[0], sc[1], sc[2])
def exitCannon(self, avId):
self.__unmakeGui()
if self.avId == avId:
self.av.reparentTo(render)
self.__resetToonToCannon(self.av)
def __resetToonToCannon(self, avatar):
pos = None
if not avatar:
if self.avId:
avatar = base.cr.doId2do.get(self.avId, None)
if avatar:
if hasattr(self, 'cannon') and self.cannon:
avatar.reparentTo(self.cannon)
avatar.setPosHpr(3, 0, 0, 90, 0, 0)
avatar.wrtReparentTo(render)
self.__resetToon(avatar)
return
def __resetToon(self, avatar, pos = None):
if avatar:
self.__stopCollisionHandler(avatar)
self.__setToonUpright(avatar, pos)
if self.localToonShooting:
self.notify.debug('toon setting position to %s' % pos)
if pos:
base.localAvatar.setPos(pos)
camera.reparentTo(avatar)
camera.setPos(self.av.cameraPositions[0][0])
place = base.cr.playGame.getPlace()
if place:
place.setState('finalBattle')
self.b_setLanded()
def __stopCollisionHandler(self, avatar):
if avatar:
avatar.loop('neutral')
if self.flyColNode:
self.flyColNode = None
if avatar == base.localAvatar:
avatar.collisionsOn()
self.flyColSphere = None
if self.flyColNodePath:
base.cTrav.removeCollider(self.flyColNodePath)
self.flyColNodePath.removeNode()
self.flyColNodePath = None
self.handler = None
return
def __setToonUpright(self, avatar, pos = None):
if avatar:
if not pos:
pos = avatar.getPos(render)
avatar.setPos(render, pos)
avatar.loop('neutral')
def b_setLanded(self):
self.d_setLanded()
def d_setLanded(self):
if self.localToonShooting:
self.sendUpdate('setLanded', [])
def setLanded(self):
self.removeAvFromCannon()
def removeAvFromCannon(self):
if self.av != None:
self.__stopCollisionHandler(self.av)
self.av.resetLOD()
place = base.cr.playGame.getPlace()
if self.av == base.localAvatar:
if place:
place.setState('finalBattle')
self.av.loop('neutral')
self.av.setPlayRate(1.0, 'run')
if self.av.getParent().getName() == 'toonOriginChange':
self.av.wrtReparentTo(render)
self.__setToonUpright(self.av)
if self.av == base.localAvatar:
self.av.startPosHprBroadcast()
self.av.startSmooth()
self.av.setScale(1, 1, 1)
self.ignore(self.av.uniqueName('disable'))
self.__destroyToonModels()
return
def setCannonWillFire(self, avId, fireTime, zRot, angle, timestamp):
self.notify.debug('setCannonWillFire: ' + str(avId) + ': zRot=' + str(zRot) + ', angle=' + str(angle) + ', time=' + str(fireTime))
if not self.model_Created:
self.notify.warning("We walked into the zone mid-flight, so we won't see it")
return
self.cannonPosition[0] = zRot
self.cannonPosition[1] = angle
self.__updateCannonPosition(avId)
task = Task(self.__fireCannonTask)
task.avId = avId
ts = globalClockDelta.localElapsedTime(timestamp)
task.fireTime = fireTime - ts
if task.fireTime < 0.0:
task.fireTime = 0.0
taskMgr.add(task, self.taskName('fireCannon'))
def __fireCannonTask(self, task):
launchTime = task.fireTime
avId = task.avId
if self.toonHead == None or not self.boss.state == 'BattleTwo':
return Task.done
2020-01-10 21:53:57 -06:00
startPos, startHpr, startVel, trajectory, timeOfImpact, hitWhat = self.__calcFlightResults(avId, launchTime)
2019-11-02 17:27:54 -05:00
self.notify.debug('start position: ' + str(startPos))
self.notify.debug('start velocity: ' + str(startVel))
self.notify.debug('time of launch: ' + str(launchTime))
self.notify.debug('time of impact: ' + str(timeOfImpact))
self.notify.debug('location of impact: ' + str(trajectory.getPos(timeOfImpact)))
head = self.toonHead
head.stopBlink()
head.stopLookAroundNow()
head.reparentTo(hidden)
juror = self.toonModel
juror.reparentTo(render)
juror.setPos(startPos)
barrelHpr = self.barrel.getHpr(render)
juror.setHpr(startHpr)
self.jurorToon.loop('swim')
self.jurorToon.setPosHpr(0, 0, -(self.jurorToon.getHeight() / 2.0), 0, 0, 0)
info = {}
info['avId'] = avId
info['trajectory'] = trajectory
info['launchTime'] = launchTime
info['timeOfImpact'] = timeOfImpact
info['hitWhat'] = hitWhat
info['toon'] = self.toonModel
info['hRot'] = self.cannonPosition[0]
info['haveWhistled'] = 0
info['maxCamPullback'] = CAMERA_PULLBACK_MIN
if self.localToonShooting:
camera.reparentTo(juror)
camera.setP(45.0)
camera.setZ(-10.0)
self.flyColSphere = CollisionSphere(0, 0, self.av.getHeight() / 2.0, 1.0)
self.flyColNode = CollisionNode(self.uniqueName('flySphere'))
self.flyColNode.setCollideMask(ToontownGlobals.WallBitmask | ToontownGlobals.FloorBitmask | ToontownGlobals.PieBitmask)
self.flyColNode.addSolid(self.flyColSphere)
self.flyColNodePath = self.jurorToon.attachNewNode(self.flyColNode)
self.flyColNodePath.setColor(1, 0, 0, 1)
self.handler = CollisionHandlerEvent()
self.handler.setInPattern(self.uniqueName('cannonHit'))
base.cTrav.addCollider(self.flyColNodePath, self.handler)
self.accept(self.uniqueName('cannonHit'), self.__handleCannonHit)
shootTask = Task(self.__shootTask, self.taskName('shootTask'))
flyTask = Task(self.__flyTask, self.taskName('flyTask'))
shootTask.info = info
flyTask.info = info
seqTask = Task.sequence(shootTask, flyTask)
taskMgr.add(seqTask, self.taskName('flyingToon') + '-' + str(avId))
self.acceptOnce(self.uniqueName('stopFlyTask'), self.__stopFlyTask)
return Task.done
def __toRadians(self, angle):
return angle * 2.0 * math.pi / 360.0
def __toDegrees(self, angle):
return angle * 360.0 / (2.0 * math.pi)
def __calcFlightResults(self, avId, launchTime):
head = self.toonHead
startPos = head.getPos(render)
startHpr = head.getHpr(render)
hpr = self.barrel.getHpr(render)
rotation = self.__toRadians(hpr[0])
angle = self.__toRadians(hpr[1])
horizVel = INITIAL_VELOCITY * math.cos(angle)
xVel = horizVel * -math.sin(rotation)
yVel = horizVel * math.cos(rotation)
zVel = INITIAL_VELOCITY * math.sin(angle)
startVel = Vec3(xVel, yVel, zVel)
trajectory = Trajectory.Trajectory(launchTime, startPos, startVel)
self.trajectory = trajectory
timeOfImpact, hitWhat = self.__calcToonImpact(trajectory)
2020-01-10 21:53:57 -06:00
return startPos, startHpr, startVel, trajectory, 3 * timeOfImpact, hitWhat
2019-11-02 17:27:54 -05:00
def __calcToonImpact(self, trajectory):
t_groundImpact = trajectory.checkCollisionWithGround(GROUND_PLANE_MIN)
if t_groundImpact >= trajectory.getStartTime():
return (t_groundImpact, self.HIT_GROUND)
else:
self.notify.error('__calcToonImpact: toon never impacts ground?')
return (0.0, self.HIT_GROUND)
def __handleCannonHit(self, collisionEntry):
if self.av == None or self.flyColNode == None:
return
interPt = collisionEntry.getSurfacePoint(render)
hitNode = collisionEntry.getIntoNode().getName()
fromNodePath = collisionEntry.getFromNodePath()
intoNodePath = collisionEntry.getIntoNodePath()
ignoredHits = ['NearBoss']
for nodeName in ignoredHits:
if hitNode == nodeName:
return
self.__stopFlyTask(self.avId)
self.__stopCollisionHandler(self.jurorToon)
if self.localToonShooting:
camera.wrtReparentTo(render)
pos = interPt
hpr = self.jurorToon.getHpr()
track = Sequence()
if self.localToonShooting:
pass
chairlist = ['trigger-chair']
for index in range(len(ToontownGlobals.LawbotBossChairPosHprs)):
chairlist.append('Chair-%s' % index)
if hitNode in chairlist:
track.append(Func(self.__hitChair, self.jurorToon, pos))
track.append(Wait(1.0))
track.append(Func(self.__setToonUpright, self.av))
if self.av == base.localAvatar:
strs = hitNode.split('-')
chairNum = int(strs[1])
self.boss.sendUpdate('hitChair', [chairNum, self.index])
else:
track.append(Func(self.__hitGround, self.jurorToon, pos))
track.append(Wait(1.0))
track.append(Func(self.__setToonUpright, self.av))
track.append(Func(self.b_setLanded))
if self.localToonShooting:
pass
if self.hitTrack:
self.hitTrack.finish()
self.hitTrack = track
self.hitTrack.start()
return
def enterCannonHit(self, collisionEntry):
pass
def __shootTask(self, task):
base.playSfx(self.sndCannonFire)
return Task.done
def __flyTask(self, task):
toon = task.info['toon']
if toon.isEmpty():
self.__resetToonToCannon(self.av)
return Task.done
curTime = task.time + task.info['launchTime']
t = min(curTime, task.info['timeOfImpact'])
self.lastT = self.t
self.t = t
deltaT = self.t - self.lastT
self.deltaT = deltaT
if t >= task.info['timeOfImpact']:
self.__resetToonToCannon(self.av)
return Task.done
pos = task.info['trajectory'].getPos(t)
toon.setFluidPos(pos)
vel = task.info['trajectory'].getVel(t)
run = math.sqrt(vel[0] * vel[0] + vel[1] * vel[1])
rise = vel[2]
theta = self.__toDegrees(math.atan(rise / run))
toon.setHpr(self.cannon.getH(render), -90 + theta, 0)
view = 2
lookAt = task.info['toon'].getPos(render)
hpr = task.info['toon'].getHpr(render)
if self.localToonShooting:
if view == 0:
camera.wrtReparentTo(render)
camera.lookAt(lookAt)
elif view == 1:
camera.reparentTo(render)
camera.setPos(render, 100, 100, 35.25)
camera.lookAt(render, lookAt)
elif view == 2:
if hpr[1] > -90:
camera.setPos(0, 0, -30)
if camera.getZ() < lookAt[2]:
camera.setZ(render, lookAt[2] + 10)
camera.lookAt(Point3(0, 0, 0))
return Task.cont
def __stopFlyTask(self, avId):
taskMgr.remove(self.taskName('flyingToon') + '-' + str(avId))
def __hitGround(self, avatar, pos, extraArgs = []):
hitP = avatar.getPos(render)
h = self.barrel.getH(render)
avatar.setPos(pos[0], pos[1], pos[2] + avatar.getHeight() / 3.0)
avatar.setHpr(h, -135, 0)
self.dustCloud.setPos(render, pos[0], pos[1], pos[2] + avatar.getHeight() / 3.0)
self.dustCloud.setScale(0.35)
self.dustCloud.play()
base.playSfx(self.sndHitGround)
avatar.hide()
def __hitChair(self, avatar, pos, extraArgs = []):
hitP = avatar.getPos(render)
h = self.barrel.getH(render)
avatar.setPos(pos[0], pos[1], pos[2] + avatar.getHeight() / 3.0)
avatar.setHpr(h, -135, 0)
self.dustCloud.setPos(render, pos[0], pos[1], pos[2] + avatar.getHeight() / 3.0)
self.dustCloud.setScale(0.35)
self.dustCloud.play()
base.playSfx(self.sndHitGround)
base.playSfx(self.sndHitChair)
avatar.hide()
def generateCannonAppearTrack(self, avatar):
self.cannon.setScale(0.1)
self.cannon.show()
kartTrack = Parallel(Sequence(ActorInterval(avatar, 'feedPet'), Func(avatar.loop, 'neutral')), Sequence(Func(self.cannon.reparentTo, avatar.rightHand), Wait(2.1), Func(self.cannon.wrtReparentTo, render), Func(self.cannon.setShear, 0, 0, 0), Parallel(LerpHprInterval(self.cannon, hpr=self.nodePath.getHpr(render), duration=1.2), ProjectileInterval(self.cannon, endPos=self.nodePath.getPos(render), duration=1.2, gravityMult=0.45)), Wait(0.2), Sequence(LerpScaleInterval(self.cannon, scale=Point3(1.1, 1.1, 0.1), duration=0.2), LerpScaleInterval(self.cannon, scale=Point3(0.9, 0.9, 0.1), duration=0.1), LerpScaleInterval(self.cannon, scale=Point3(1.0, 1.0, 0.1), duration=0.1), LerpScaleInterval(self.cannon, scale=Point3(1.0, 1.0, 1.1), duration=0.2), LerpScaleInterval(self.cannon, scale=Point3(1.0, 1.0, 0.9), duration=0.1), LerpScaleInterval(self.cannon, scale=Point3(1.0, 1.0, 1.0), duration=0.1), Func(self.cannon.wrtReparentTo, self.nodePath))))
return kartTrack