250 lines
8.8 KiB
Python
250 lines
8.8 KiB
Python
import math
|
|
from panda3d.core import *
|
|
from direct.interval.MetaInterval import Sequence, Parallel
|
|
from direct.interval.FunctionInterval import Func
|
|
from direct.interval.LerpInterval import LerpScaleInterval, LerpColorScaleInterval
|
|
from direct.showbase.PythonUtil import bound
|
|
from toontown.toon import ToonHead
|
|
from toontown.minigame.CannonGameGlobals import *
|
|
from toontown.toonbase import ToontownGlobals
|
|
from toontown.parties.PartyUtils import toRadians, calcVelocity
|
|
from direct.showbase.PythonUtil import StackTrace
|
|
from otp.nametag.NametagFloat3d import NametagFloat3d
|
|
from otp.nametag.Nametag import Nametag
|
|
CANNON_ROTATION_MIN = -70
|
|
CANNON_ROTATION_MAX = 70
|
|
INITIAL_VELOCITY = 80.0
|
|
CANNON_BARREL_TOONHEAD_Y = 6.0
|
|
|
|
class Cannon:
|
|
notify = directNotify.newCategory('DistributedPartyCannon')
|
|
|
|
def __init__(self, parent, pos = Point3(0, 0, 0)):
|
|
self.__previousRotation = 0.0
|
|
self.__previousAngle = 0.0
|
|
self._rotation = 0.0
|
|
self._angle = 0.0
|
|
self._position = pos
|
|
self._parent = parent
|
|
self.parentNode = None
|
|
self.cannonNode = None
|
|
self.barrelNode = None
|
|
self.sndCannonMove = None
|
|
self.sndCannonFire = None
|
|
self.collSphere = None
|
|
self.collNode = None
|
|
self.collNodePath = None
|
|
self.toonInside = None
|
|
self.toonHead = None
|
|
self.toonOriginalScale = 0.0
|
|
self.toonParentNode = None
|
|
return
|
|
|
|
def reset(self):
|
|
self.setRotation(0)
|
|
self.setAngle((CANNON_ANGLE_MIN + CANNON_ANGLE_MAX * 0.5) * 0.5)
|
|
self.parentNode.setPos(self._position)
|
|
self.updateModel()
|
|
|
|
def load(self, nodeName):
|
|
self.parentNode = NodePath(nodeName)
|
|
self.cannonNode = loader.loadModel('phase_4/models/minigames/toon_cannon')
|
|
self.cannonNode.reparentTo(self.parentNode)
|
|
self.barrelNode = self.cannonNode.find('**/cannon')
|
|
self.shadowNode = self.cannonNode.find('**/square_drop_shadow')
|
|
self.smokeNode = loader.loadModel('phase_4/models/props/test_clouds')
|
|
self.smokeNode.setBillboardPointEye()
|
|
self.sndCannonMove = base.loadSfx('phase_4/audio/sfx/MG_cannon_adjust.ogg')
|
|
self.sndCannonFire = base.loadSfx('phase_4/audio/sfx/MG_cannon_fire_alt.ogg')
|
|
self.collSphere = CollisionSphere(0, 0, 0, self.getSphereRadius())
|
|
self.collSphere.setTangible(1)
|
|
self.collNode = CollisionNode(self.getCollisionName())
|
|
self.collNode.setCollideMask(ToontownGlobals.WallBitmask)
|
|
self.collNode.addSolid(self.collSphere)
|
|
self.collNodePath = self.parentNode.attachNewNode(self.collNode)
|
|
|
|
def unload(self):
|
|
self.__cleanupToonInside()
|
|
if self.cannonNode:
|
|
self.cannonNode.removeNode()
|
|
self.cannonNode = None
|
|
if self.smokeNode:
|
|
self.smokeNode.removeNode()
|
|
self.smokeNode = None
|
|
del self.sndCannonMove
|
|
del self.sndCannonFire
|
|
del self._position
|
|
self.ignoreAll()
|
|
return
|
|
|
|
def updateModel(self, rotation = None, angle = None):
|
|
if rotation:
|
|
self.rotation = rotation
|
|
if angle:
|
|
self.angle = angle
|
|
self.cannonNode.setHpr(self._rotation, 0, 0)
|
|
self.barrelNode.setHpr(0, self._angle, 0)
|
|
maxP = 90
|
|
newP = self.barrelNode.getP()
|
|
yScale = 1 - 0.5 * float(newP) / maxP
|
|
self.shadowNode.setScale(1, yScale, 1)
|
|
|
|
def playFireSequence(self):
|
|
self.smokeNode.reparentTo(self.barrelNode)
|
|
self.smokeNode.setPos(0, 6, -3)
|
|
self.smokeNode.setScale(0.5)
|
|
self.smokeNode.wrtReparentTo(render)
|
|
track = Sequence(Parallel(LerpScaleInterval(self.smokeNode, 0.5, 3), LerpColorScaleInterval(self.smokeNode, 0.5, Vec4(2, 2, 2, 0))), Func(self.smokeNode.reparentTo, hidden), Func(self.smokeNode.clearColorScale))
|
|
base.playSfx(self.sndCannonFire)
|
|
track.start()
|
|
|
|
def loopMovingSound(self):
|
|
base.playSfx(self.sndCannonMove, looping=1)
|
|
|
|
def stopMovingSound(self):
|
|
self.sndCannonMove.stop()
|
|
|
|
def show(self):
|
|
self.reset()
|
|
self.parentNode.reparentTo(self._parent)
|
|
|
|
def hide(self):
|
|
self.parentNode.reparentTo(hidden)
|
|
|
|
def placeToonInside(self, toon):
|
|
self.__setToonInside(toon)
|
|
self.__createToonHead(toon)
|
|
self.__placeToon()
|
|
|
|
def __setToonInside(self, toon):
|
|
self.toonInside = toon
|
|
toonName = 'None'
|
|
if toon:
|
|
toonName = toon.getName()
|
|
self.notify.debug('__setToonInside self.toonInside=%s\nstack=%s' % (toonName, StackTrace().compact()))
|
|
self.toonInside.stopSmooth()
|
|
self.toonOriginalScale = toon.getScale()
|
|
toon.useLOD(1000)
|
|
self.toonParentNode = render.attachNewNode('toonOriginChange')
|
|
self.toonInside.wrtReparentTo(self.toonParentNode)
|
|
self.toonInside.setPosHpr(0, 0, -(self.toonInside.getHeight() / 2.0), 0, -90, 0)
|
|
|
|
def __createToonHead(self, toon):
|
|
self.toonHead = ToonHead.ToonHead()
|
|
self.toonHead.setupHead(toon.style)
|
|
self.toonHead.reparentTo(hidden)
|
|
tag = NametagFloat3d()
|
|
tag.setContents(Nametag.CSpeech | Nametag.CThought)
|
|
tag.setBillboardOffset(0)
|
|
tag.setAvatar(self.toonHead)
|
|
toon.nametag.addNametag(tag)
|
|
tagPath = self.toonHead.attachNewNode(tag)
|
|
tagPath.setPos(0, 0, 1)
|
|
self.toonHead.tag = tag
|
|
|
|
def __placeToon(self):
|
|
self.showToonHead()
|
|
self.toonHead.setPosHpr(0, CANNON_BARREL_TOONHEAD_Y, 0, 0, -45, 0)
|
|
scale = self.toonOriginalScale
|
|
self.toonHead.setScale(render, scale[0], scale[1], scale[2])
|
|
self.toonParentNode.reparentTo(hidden)
|
|
self.toonParentNode.setPos(self.getToonFirePos())
|
|
|
|
def showToonHead(self):
|
|
if self.toonHead:
|
|
self.toonHead.startBlink()
|
|
self.toonHead.startLookAround()
|
|
self.toonHead.reparentTo(self.barrelNode)
|
|
|
|
def hideToonHead(self):
|
|
if self.toonHead:
|
|
self.toonHead.stopBlink()
|
|
self.toonHead.stopLookAroundNow()
|
|
self.toonHead.reparentTo(hidden)
|
|
|
|
def removeToonReadyToFire(self):
|
|
toon = self.toonInside
|
|
self.toonInside.wrtReparentTo(render)
|
|
y = self.toonHead.getY(self.barrelNode) - (self.toonInside.getHeight() - self.toonHead.getHeight())
|
|
self.toonInside.setPosHpr(self.barrelNode, 0, y, 0, 0, -90, 0)
|
|
return self.__removeToon()
|
|
|
|
def removeToonDidNotFire(self):
|
|
self.toonInside.reparentTo(self.cannonNode)
|
|
self.toonInside.setPos(2, -4, 0)
|
|
self.toonInside.wrtReparentTo(render)
|
|
return self.__removeToon()
|
|
|
|
def __removeToon(self):
|
|
self.stopMovingSound()
|
|
toonNode = self.toonParentNode
|
|
self.toonInside.resetLOD()
|
|
self.hideToonHead()
|
|
self.__cleanupToonInside()
|
|
return toonNode
|
|
|
|
def __cleanupToonInside(self):
|
|
toonName = 'None'
|
|
if self.toonInside:
|
|
toonName = self.toonInside.getName()
|
|
self.notify.debug('__cleanupToonInside self.toonInside=%s\nstack=%s' % (toonName, StackTrace().compact()))
|
|
if self.toonHead != None:
|
|
self.hideToonHead()
|
|
if hasattr(self.toonInside, 'nametag'):
|
|
self.toonInside.nametag.removeNametag(self.toonHead.tag)
|
|
self.toonHead.delete()
|
|
self.toonHead = None
|
|
self.toonInside = None
|
|
self.toonParentNode = None
|
|
return
|
|
|
|
def getSphereRadius(self):
|
|
return 1.5
|
|
|
|
def getCollisionName(self):
|
|
return self.parentNode.getName() + 'Collision'
|
|
|
|
def getEnterCollisionName(self):
|
|
return 'enter' + self.getCollisionName()
|
|
|
|
def isToonInside(self):
|
|
return self.toonHead != None
|
|
|
|
def getToonInside(self):
|
|
return self.toonInside
|
|
|
|
def setRotation(self, rotation):
|
|
self.__previousRotation = self._rotation
|
|
self._rotation = bound(rotation, CANNON_ROTATION_MIN, CANNON_ROTATION_MAX)
|
|
|
|
def getRotation(self):
|
|
return self._rotation
|
|
|
|
def setAngle(self, angle):
|
|
self.__previousAngle = self._angle
|
|
self._angle = bound(angle, CANNON_ANGLE_MIN, CANNON_ANGLE_MAX)
|
|
|
|
def getAngle(self):
|
|
return self._angle
|
|
|
|
def hasMoved(self):
|
|
return self.__previousRotation != self._rotation or self.__previousAngle != self._angle
|
|
|
|
def getBarrelHpr(self, node):
|
|
return self.barrelNode.getHpr(node)
|
|
|
|
def getToonFirePos(self):
|
|
if self.toonHead:
|
|
return self.toonHead.getPos(render)
|
|
return Point3.zero()
|
|
|
|
def getToonFireHpr(self):
|
|
if self.toonHead:
|
|
return self.toonHead.getHpr(render)
|
|
return Point3.zero()
|
|
|
|
def getToonFireVel(self):
|
|
hpr = self.barrelNode.getHpr(render)
|
|
rotation = toRadians(hpr[0])
|
|
angle = toRadians(hpr[1])
|
|
return calcVelocity(rotation, angle, initialVelocity=INITIAL_VELOCITY)
|