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)