1801d2b9fb
UD/AI + Client boots up.
449 lines
17 KiB
Python
449 lines
17 KiB
Python
from panda3d.core import *
|
|
from direct.distributed.DistributedObject import DistributedObject
|
|
from direct.task.Task import Task
|
|
from toontown.minigame import CannonGameGlobals
|
|
from toontown.minigame.CannonGameGlobals import *
|
|
from toontown.parties.Cannon import Cannon
|
|
from toontown.parties.CannonGui import CannonGui
|
|
from toontown.parties import PartyGlobals
|
|
from toontown.parties.DistributedPartyCannonActivity import DistributedPartyCannonActivity
|
|
LAND_TIME = 2
|
|
WORLD_SCALE = 2.0
|
|
GROUND_SCALE = 1.4 * WORLD_SCALE
|
|
CANNON_SCALE = 1.0
|
|
FAR_PLANE_DIST = 600 * WORLD_SCALE
|
|
GROUND_PLANE_MIN = -15
|
|
CANNON_Y = -int(CannonGameGlobals.TowerYRange / 2 * 1.3)
|
|
CANNON_X_SPACING = 12
|
|
CANNON_Z = 20
|
|
CANNON_ROTATION_MIN = -55
|
|
CANNON_ROTATION_MAX = 50
|
|
CANNON_ROTATION_VEL = 15.0
|
|
ROTATIONCANNON_ANGLE_MIN = 15
|
|
CANNON_ANGLE_MAX = 85
|
|
CANNON_ANGLE_VEL = 15.0
|
|
CANNON_MOVE_UPDATE_FREQ = 0.5
|
|
CAMERA_PULLBACK_MIN = 20
|
|
CAMERA_PULLBACK_MAX = 40
|
|
MAX_LOOKAT_OFFSET = 80
|
|
TOON_TOWER_THRESHOLD = 150
|
|
SHADOW_Z_OFFSET = 0.5
|
|
TOWER_HEIGHT = 43.85
|
|
TOWER_RADIUS = 10.5
|
|
BUCKET_HEIGHT = 36
|
|
TOWER_Y_RANGE = CannonGameGlobals.TowerYRange
|
|
TOWER_X_RANGE = int(TOWER_Y_RANGE / 2.0)
|
|
INITIAL_VELOCITY = 80.0
|
|
WHISTLE_SPEED = INITIAL_VELOCITY * 0.35
|
|
|
|
class DistributedPartyCannon(DistributedObject, Cannon):
|
|
notify = directNotify.newCategory('DistributedPartyCannon')
|
|
LOCAL_CANNON_MOVE_TASK = 'localCannonMoveTask'
|
|
|
|
def __init__(self, cr):
|
|
DistributedObject.__init__(self, cr)
|
|
Cannon.__init__(self, parent=self.getParentNodePath())
|
|
self.localCannonMoving = False
|
|
self.active = False
|
|
self.activityDoId = 0
|
|
self.activity = None
|
|
self.gui = None
|
|
self.toonInsideAvId = 0
|
|
self.sign = None
|
|
self.controllingToonAvId = None
|
|
return
|
|
|
|
def generateInit(self):
|
|
self.load()
|
|
self.activate()
|
|
|
|
def load(self):
|
|
self.notify.debug('load')
|
|
Cannon.load(self, self.uniqueName('Cannon'))
|
|
if base.cr and base.cr.partyManager and base.cr.partyManager.getShowDoid():
|
|
nameText = TextNode('nameText')
|
|
nameText.setCardAsMargin(0.1, 0.1, 0.1, 0.1)
|
|
nameText.setCardDecal(True)
|
|
nameText.setCardColor(1.0, 1.0, 1.0, 0.0)
|
|
r = 232.0 / 255.0
|
|
g = 169.0 / 255.0
|
|
b = 23.0 / 255.0
|
|
nameText.setTextColor(r, g, b, 1)
|
|
nameText.setAlign(nameText.ACenter)
|
|
nameText.setShadowColor(0, 0, 0, 1)
|
|
nameText.setText(str(self.doId))
|
|
namePlate = self.parentNode.attachNewNode(nameText)
|
|
namePlate.setDepthWrite(0)
|
|
namePlate.setPos(0, 0, 8)
|
|
namePlate.setScale(3)
|
|
|
|
def announceGenerate(self):
|
|
self.sign = self.activity.sign.instanceUnderNode(self.activity.getParentNodePath(), self.uniqueName('sign'))
|
|
self.sign.reparentTo(self.activity.getParentNodePath())
|
|
self.sign.setPos(self.parentNode, self.sign.getPos())
|
|
|
|
def unload(self):
|
|
self.notify.debug('unload')
|
|
if self.gui is not None:
|
|
self.gui.unload()
|
|
del self.gui
|
|
Cannon.unload(self)
|
|
if self.sign is not None:
|
|
self.sign.removeNode()
|
|
self.sign = None
|
|
self.ignoreAll()
|
|
return
|
|
|
|
def getParentNodePath(self):
|
|
if hasattr(base.cr.playGame, 'hood') and base.cr.playGame.hood and hasattr(base.cr.playGame.hood, 'loader') and base.cr.playGame.hood.loader and hasattr(base.cr.playGame.hood.loader, 'geom') and base.cr.playGame.hood.loader.geom:
|
|
return base.cr.playGame.hood.loader.geom
|
|
else:
|
|
self.notify.warning('Hood or loader not created, defaulting to render')
|
|
return render
|
|
|
|
def disable(self):
|
|
self.notify.debug('disable')
|
|
self.ignoreAll()
|
|
self.__disableCannonControl()
|
|
self.setMovie(PartyGlobals.CANNON_MOVIE_CLEAR, 0)
|
|
|
|
def delete(self):
|
|
self.deactivate()
|
|
self.unload()
|
|
DistributedObject.delete(self)
|
|
|
|
def destroy(self):
|
|
self.notify.debug('destroy')
|
|
DistributedObject.destroy(self)
|
|
|
|
def setPosHpr(self, x, y, z, h, p, r):
|
|
self.parentNode.setPosHpr(x, y, z, h, p, r)
|
|
|
|
def setActivityDoId(self, doId):
|
|
self.activityDoId = doId
|
|
self.activity = base.cr.doId2do[doId]
|
|
|
|
def activate(self):
|
|
self.accept(self.getEnterCollisionName(), self.__handleToonCollisionWithCannon)
|
|
Cannon.show(self)
|
|
self.active = True
|
|
|
|
def deactivate(self):
|
|
self.ignore(self.getEnterCollisionName())
|
|
Cannon.hide(self)
|
|
self.active = False
|
|
|
|
def setMovie(self, mode, avId):
|
|
self.notify.debug('%s setMovie(%s, %s)' % (self.doId, avId, mode))
|
|
if mode == PartyGlobals.CANNON_MOVIE_CLEAR:
|
|
self.setClear()
|
|
elif mode == PartyGlobals.CANNON_MOVIE_FORCE_EXIT:
|
|
self.exitCannon(avId)
|
|
self.setClear()
|
|
elif mode == PartyGlobals.CANNON_MOVIE_LOAD:
|
|
self.enterCannon(avId)
|
|
elif mode == PartyGlobals.CANNON_MOVIE_LANDED:
|
|
self.setLanded(avId)
|
|
else:
|
|
self.notify.error('setMovie Unhandled case mode=%d avId=%d' % (mode, avId))
|
|
|
|
def __handleToonCollisionWithCannon(self, collEntry):
|
|
self.notify.debug('collEntry: %s' % collEntry)
|
|
if base.cr.playGame.getPlace().getState() == 'walk' and self.toonInsideAvId == 0:
|
|
base.cr.playGame.getPlace().setState('activity')
|
|
self.d_requestEnter()
|
|
|
|
def d_requestEnter(self):
|
|
self.sendUpdate('requestEnter', [])
|
|
|
|
def requestExit(self):
|
|
self.notify.debug('requestExit')
|
|
base.localAvatar.reparentTo(render)
|
|
base.cr.playGame.getPlace().setState('walk')
|
|
|
|
def __avatarGone(self, avId):
|
|
if self.toonInsideAvId == avId:
|
|
self.notify.debug('__avatarGone in if')
|
|
if self.toonInside and not self.toonInside.isEmpty():
|
|
self.removeToonDidNotFire()
|
|
self.setMovie(PartyGlobals.CANNON_MOVIE_CLEAR, 0)
|
|
else:
|
|
self.notify.debug('__avatarGone in else, self.toonInsideAvId=%s avId=%s' % (self.toonInsideAvId, avId))
|
|
|
|
def enterCannon(self, avId):
|
|
if avId == base.localAvatar.doId:
|
|
base.localAvatar.pose('lose', 110)
|
|
base.localAvatar.pose('slip-forward', 25)
|
|
base.cr.playGame.getPlace().setState('activity')
|
|
base.localAvatar.collisionsOff()
|
|
camera.reparentTo(self.barrelNode)
|
|
camera.setPos(0, -2, 5)
|
|
camera.setP(-20)
|
|
if not self.activity.hasPlayedBefore():
|
|
self.activity.displayRules()
|
|
self.acceptOnce(DistributedPartyCannonActivity.RULES_DONE_EVENT, self.__enableCannonControl)
|
|
else:
|
|
self.__enableCannonControl()
|
|
self.controllingToonAvId = avId
|
|
if avId in self.cr.doId2do:
|
|
self.toonInsideAvId = avId
|
|
self.notify.debug('enterCannon self.toonInsideAvId=%d' % self.toonInsideAvId)
|
|
toon = base.cr.doId2do[avId]
|
|
if toon:
|
|
self.acceptOnce(toon.uniqueName('disable'), self.__avatarGone, extraArgs=[avId])
|
|
toon.stopSmooth()
|
|
toon.dropShadow.hide()
|
|
self.placeToonInside(toon)
|
|
else:
|
|
self.__avatarGone(avId)
|
|
else:
|
|
self.notify.warning('Unknown avatar %d in cannon %d' % (avId, self.doId))
|
|
|
|
def exitCannon(self, avId):
|
|
if avId == base.localAvatar.doId:
|
|
self.activity.finishRules()
|
|
self.ignore(DistributedPartyCannonActivity.RULES_DONE_EVENT)
|
|
self.ignoreDisableForAvId(avId)
|
|
if self.gui and avId == base.localAvatar.doId:
|
|
self.gui.unload()
|
|
toon = base.cr.doId2do.get(avId)
|
|
if toon and self.getToonInside() == toon:
|
|
self.resetToon()
|
|
else:
|
|
self.notify.debug('not resetting toon, toon=%s, self.getToonInside()=%s' % (toon, self.getToonInside()))
|
|
|
|
def resetToon(self, pos = None):
|
|
self.notify.debug('resetToon')
|
|
toon = self.getToonInside()
|
|
toonInsideAvId = self.toonInsideAvId
|
|
self.notify.debug('%d resetToon self.toonInsideAvId=%d' % (self.doId, self.toonInsideAvId))
|
|
self.removeToonDidNotFire()
|
|
self.__setToonUpright(toon, pos)
|
|
if toonInsideAvId == base.localAvatar.doId:
|
|
self.notify.debug('%d resetToon toonInsideAvId ==localAvatar.doId' % self.doId)
|
|
if pos:
|
|
self.notify.debug('toon setting position to %s' % pos)
|
|
base.localAvatar.setPos(pos)
|
|
camera.reparentTo(base.localAvatar)
|
|
base.localAvatar.collisionsOn()
|
|
base.localAvatar.startPosHprBroadcast()
|
|
base.localAvatar.enableAvatarControls()
|
|
self.notify.debug('currentState=%s, requesting walk' % base.cr.playGame.getPlace().getState())
|
|
base.cr.playGame.getPlace().setState('walk')
|
|
self.notify.debug('after request walk currentState=%s,' % base.cr.playGame.getPlace().getState())
|
|
toon.dropShadow.show()
|
|
self.d_setLanded()
|
|
|
|
def __setToonUpright(self, toon, pos = None):
|
|
if not pos:
|
|
pos = toon.getPos(render)
|
|
toon.setPos(render, pos)
|
|
toon.loop('neutral')
|
|
toon.lookAt(self.parentNode)
|
|
toon.setP(0)
|
|
toon.setR(0)
|
|
toon.setScale(1, 1, 1)
|
|
|
|
def d_setLanded(self):
|
|
self.notify.debugStateCall(self)
|
|
if self.toonInsideAvId == base.localAvatar.doId:
|
|
self.sendUpdate('setLanded', [base.localAvatar.doId])
|
|
|
|
def setLanded(self, avId):
|
|
self.removeAvFromCannon(avId)
|
|
self.ignoreDisableForAvId(avId)
|
|
|
|
def removeAvFromCannon(self, avId):
|
|
place = base.cr.playGame.getPlace()
|
|
av = base.cr.doId2do.get(avId)
|
|
print('removeAvFromCannon')
|
|
if place:
|
|
if not hasattr(place, 'fsm'):
|
|
return
|
|
placeState = place.fsm.getCurrentState().getName()
|
|
print(placeState)
|
|
if placeState != 'fishing':
|
|
if av != None:
|
|
av.startSmooth()
|
|
self.__destroyToonModels(avId)
|
|
return
|
|
self.notify.debug('%s removeAvFromCannon' % self.doId)
|
|
if av != None:
|
|
self.notify.debug('%d removeAvFromCannon: destroying toon models' % self.doId)
|
|
av.resetLOD()
|
|
if av == base.localAvatar:
|
|
if place:
|
|
place.fsm.request('walk')
|
|
av.setPlayRate(1.0, 'run')
|
|
if av.nametag and self.toonHead:
|
|
av.nametag.removeNametag(self.toonHead.tag)
|
|
if av.getParent().getName() == 'toonOriginChange':
|
|
av.wrtReparentTo(render)
|
|
self.__setToonUpright(av)
|
|
if av == base.localAvatar:
|
|
av.startPosHprBroadcast()
|
|
av.startSmooth()
|
|
av.setScale(1, 1, 1)
|
|
self.ignore(av.uniqueName('disable'))
|
|
self.__destroyToonModels(avId)
|
|
return
|
|
|
|
def __destroyToonModels(self, avId):
|
|
av = base.cr.doId2do.get(avId)
|
|
if not av:
|
|
return
|
|
if av != None:
|
|
av.dropShadow.show()
|
|
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
|
|
av = None
|
|
self.lastWakeTime = 0
|
|
self.localToonShooting = 0
|
|
if self.toonHead != None:
|
|
self.toonHead.reparentTo(hidden)
|
|
self.toonHead.stopBlink()
|
|
self.toonHead.stopLookAroundNow()
|
|
self.toonHead.delete()
|
|
self.toonHead = None
|
|
self.model_Created = 0
|
|
return
|
|
|
|
def setClear(self):
|
|
toon = base.cr.doId2do.get(self.toonInsideAvId)
|
|
toonName = 'None'
|
|
self.ignoreDisableForAvId(self.toonInsideAvId)
|
|
if toon and self.isToonInside():
|
|
toonName = toon.getName()
|
|
toon.resetLOD()
|
|
toon.setPlayRate(1.0, 'run')
|
|
if toon.getParent().getName() == 'toonOriginChange':
|
|
toon.wrtReparentTo(render)
|
|
self.__setToonUpright(toon)
|
|
toon.startSmooth()
|
|
toon.setScale(1, 1, 1)
|
|
self.ignore(toon.uniqueName('disable'))
|
|
if self.toonInsideAvId == base.localAvatar.doId:
|
|
toon.startPosHprBroadcast()
|
|
try:
|
|
base.localAvatar.enableAvatarControls()
|
|
except:
|
|
self.notify.warning("couldn't enable avatar controls")
|
|
|
|
base.cr.playGame.getPlace().setState('walk')
|
|
else:
|
|
self.notify.debug('setClear in else toon=%s, self.isToonInsde()=%s' % (toonName, self.isToonInside()))
|
|
self.toonInsideAvId = 0
|
|
self.notify.debug('setClear self.toonInsideAvId=%d' % self.toonInsideAvId)
|
|
if self.controllingToonAvId == base.localAvatar.doId:
|
|
self.notify.debug('set_clear turning off cannon control')
|
|
self.__disableCannonControl()
|
|
self.controllingToonAvId = 0
|
|
|
|
def __enableCannonControl(self):
|
|
if not self.gui:
|
|
self.gui = self.activity.gui
|
|
self.gui.load()
|
|
self.gui.enable(timer=PartyGlobals.CANNON_TIMEOUT)
|
|
self.d_setTimeout()
|
|
self.accept(CannonGui.FIRE_PRESSED, self.__handleFirePressed)
|
|
self.__startLocalCannonMoveTask()
|
|
|
|
def d_setTimeout(self):
|
|
self.sendUpdate('setTimeout')
|
|
|
|
def __disableCannonControl(self):
|
|
if self.gui:
|
|
self.gui.unload()
|
|
self.ignore(CannonGui.FIRE_PRESSED)
|
|
self.__stopLocalCannonMoveTask()
|
|
|
|
def __startLocalCannonMoveTask(self):
|
|
self.localCannonMoving = False
|
|
task = Task(self.__localCannonMoveTask)
|
|
task.lastPositionBroadcastTime = 0.0
|
|
taskMgr.add(task, self.LOCAL_CANNON_MOVE_TASK)
|
|
|
|
def __stopLocalCannonMoveTask(self):
|
|
taskMgr.remove(self.LOCAL_CANNON_MOVE_TASK)
|
|
if self.localCannonMoving:
|
|
self.localCannonMoving = False
|
|
self.stopMovingSound()
|
|
|
|
def __localCannonMoveTask(self, task):
|
|
rotVel = 0
|
|
if self.gui.leftPressed:
|
|
rotVel += CANNON_ROTATION_VEL
|
|
if self.gui.rightPressed:
|
|
rotVel -= CANNON_ROTATION_VEL
|
|
self.setRotation(self.getRotation() + rotVel * globalClock.getDt())
|
|
angVel = 0
|
|
if self.gui.upPressed:
|
|
angVel += CANNON_ANGLE_VEL
|
|
if self.gui.downPressed:
|
|
angVel -= CANNON_ANGLE_VEL
|
|
self.setAngle(self.getAngle() + angVel * globalClock.getDt())
|
|
if self.hasMoved():
|
|
if not self.localCannonMoving:
|
|
self.localCannonMoving = True
|
|
self.loopMovingSound()
|
|
self.updateModel()
|
|
if task.time - task.lastPositionBroadcastTime > CANNON_MOVE_UPDATE_FREQ:
|
|
self.notify.debug('Broadcast local cannon %s position' % self.doId)
|
|
task.lastPositionBroadcastTime = task.time
|
|
self.__broadcastLocalCannonPosition()
|
|
elif self.localCannonMoving:
|
|
self.localCannonMoving = False
|
|
self.stopMovingSound()
|
|
self.__broadcastLocalCannonPosition()
|
|
self.notify.debug('Cannon Rot = %s, Angle = %s' % (self._rotation, self._angle))
|
|
return Task.cont
|
|
|
|
def __broadcastLocalCannonPosition(self):
|
|
self.d_setCannonPosition(self._rotation, self._angle)
|
|
|
|
def d_setCannonPosition(self, zRot, angle):
|
|
self.sendUpdate('setCannonPosition', [zRot, angle])
|
|
|
|
def updateCannonPosition(self, avId, zRot, angle):
|
|
if avId and avId == self.toonInsideAvId and avId != base.localAvatar.doId:
|
|
self.notify.debug('update cannon %s position zRot = %d, angle = %d' % (self.doId, zRot, angle))
|
|
self.setRotation(zRot)
|
|
self.setAngle(angle)
|
|
self.updateModel()
|
|
|
|
def __handleFirePressed(self):
|
|
self.notify.debug('fire pressed')
|
|
self.__disableCannonControl()
|
|
self.__broadcastLocalCannonPosition()
|
|
self.d_setCannonLit(self._rotation, self._angle)
|
|
|
|
def d_setCannonLit(self, zRot, angle):
|
|
self.sendUpdate('setCannonLit', [zRot, angle])
|
|
|
|
def fire(self):
|
|
if base.localAvatar.doId == self.controllingToonAvId:
|
|
self.__disableCannonControl()
|
|
self.d_setFired()
|
|
self.playFireSequence()
|
|
self.controllingToonAvId = None
|
|
return
|
|
|
|
def d_setFired(self):
|
|
self.sendUpdate('setFired', [])
|
|
|
|
def ignoreDisableForAvId(self, avId):
|
|
toon = base.cr.doId2do.get(avId)
|
|
if toon:
|
|
self.notify.debug('ignoring %s' % toon.uniqueName('disable'))
|
|
self.ignore(toon.uniqueName('disable'))
|
|
else:
|
|
self.notify.debug('ignoring disable-%s' % self.toonInsideAvId)
|
|
self.ignore('disable-%s' % self.toonInsideAvId)
|