1801d2b9fb
UD/AI + Client boots up.
876 lines
34 KiB
Python
876 lines
34 KiB
Python
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
|
|
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 *
|
|
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)
|
|
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')
|
|
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:
|
|
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
|
|
startPos, startHpr, startVel, trajectory, timeOfImpact, hitWhat = self.__calcFlightResults(avId, launchTime)
|
|
|
|
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)
|
|
return startPos, startHpr, startVel, trajectory, 3 * timeOfImpact, hitWhat
|
|
|
|
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
|