class DistributedArcadeBattleZoneAI(DistributedBattleZoneAI): notify = directNotify.newCategory('DistributedArcadeBattleZoneAI') def __init__(self, air): DistributedBattleZoneAI.__init__(self, air) self.battleType = BattleGlobals.BTArcade self.matchData = None self.fsm = ClassicFSM('DistributedArcadeBattleZoneAI', [ State('off', self.enterOff, self.exitOff), ], 'off', 'off') self.readyAvatars = [] # Variables related to turrets self.turretMgr = None def announceGenerate(self): DistributedBattleZoneAI.announceGenerate(self) self.turretMgr = DistributedPieTurretManagerAI(self.air) self.turretMgr.generateWithRequired(self.zoneId) self.fsm.enterInitialState() def enterOff(self): pass def exitOff(self): pass
class Walk(StateData): notify = directNotify.newCategory("Walk") def __init__(self, doneEvent): StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('Walk', [ State('off', self.enterOff, self.exitOff, ['walking', 'deadWalking']), State('walking', self.enterWalking, self.exitWalking), State('deadWalking', self.enterDeadWalking, self.exitDeadWalking)], 'off', 'off') self.fsm.enterInitialState() def unload(self): del self.fsm def enter(self, wantMouse = 0): base.localAvatar.startPlay(wantMouse = wantMouse) def exit(self): if base.localAvatarReachable(): base.localAvatar.lastState = None self.fsm.request('off') base.localAvatar.stopPlay() def enterOff(self): pass def exitOff(self): pass def enterWalking(self): if base.localAvatar.getHealth() > 0: base.localAvatar.startTrackAnimToSpeed() #base.localAvatar.setWalkSpeedNormal() else: self.fsm.request('deadWalking') def exitWalking(self): base.localAvatar.stopTrackAnimToSpeed() def enterDeadWalking(self): base.localAvatar.startTrackAnimToSpeed() base.localAvatar.setWalkSpeedSlow() base.taskMgr.add(self.__watchForPositiveHP, base.localAvatar.uniqueName('watchforPositiveHP')) def __watchForPositiveHP(self, task): if base.localAvatar.getHealth() > 0: self.fsm.request('walking') return task.done return task.cont def exitDeadWalking(self): base.taskMgr.remove(base.localAvatar.uniqueName('watchforPositiveHP')) base.localAvatar.stopTrackAnimToSpeed()
class ToonInterior(Place.Place): notify = directNotify.newCategory("ToonInterior") def __init__(self, hood, parentFSM, doneEvent): self.parentFSM = parentFSM Place.Place.__init__(self, hood, doneEvent) self.interior = True self.fsm = ClassicFSM('ToonInterior', [ State('start', self.enterStart, self.exitStart, ['doorOut', 'teleportIn']), State('walk', self.enterWalk, self.exitWalk, ['stop', 'doorIn', 'shtickerBook', 'teleportOut']), State('shtickerBook', self.enterShtickerBook, self.exitShtickerBook, ['teleportOut', 'walk']), State('teleportOut', self.enterTeleportOut, self.exitTeleportOut, ['teleportIn', 'stop']), State('teleportIn', self.enterTeleportIn, self.exitTeleportIn, ['walk', 'stop']), State('tunnelOut', self.enterTunnelOut, self.exitTunnelOut, ['walk']), State('tunnelIn', self.enterTunnelIn, self.exitTunnelIn, ['stop']), State('stop', self.enterStop, self.exitStop, ['walk', 'died', 'teleportOut', 'doorIn']), State('doorIn', self.enterDoorIn, self.exitDoorIn, ['stop']), State('doorOut', self.enterDoorOut, self.exitDoorOut, ['walk']), State('final', self.enterFinal, self.exitFinal, ['final']) ], 'start', 'final') def enter(self, requestStatus): Place.Place.enter(self) self.fsm.enterInitialState() base.playMusic(self.loader.interiorSong, looping=1) self.fsm.request(requestStatus['how'], [requestStatus]) return def exit(self): base.stopMusic() Place.Place.exit(self) def load(self): Place.Place.load(self) self.parentFSM.getStateNamed('toonInterior').addChild(self.fsm) def unload(self): self.parentFSM.getStateNamed('toonInterior').removeChild(self.fsm) del self.fsm del self.parentFSM self.ignoreAll() Place.Place.unload(self) return
class ToonInterior(Place.Place): notify = directNotify.newCategory('ToonInterior') def __init__(self, hood, parentFSM, doneEvent): self.parentFSM = parentFSM Place.Place.__init__(self, hood, doneEvent) self.fsm = ClassicFSM('ToonInterior', [State('start', self.enterStart, self.exitStart, ['doorOut', 'teleportIn']), State('walk', self.enterWalk, self.exitWalk, ['stop', 'doorIn', 'shtickerBook', 'teleportOut']), State('shtickerBook', self.enterShtickerBook, self.exitShtickerBook, ['teleportOut', 'walk']), State('teleportOut', self.enterTeleportOut, self.exitTeleportOut, ['teleportIn', 'stop']), State('teleportIn', self.enterTeleportIn, self.exitTeleportIn, ['walk', 'stop']), State('tunnelOut', self.enterTunnelOut, self.exitTunnelOut, ['walk']), State('tunnelIn', self.enterTunnelIn, self.exitTunnelIn, ['stop']), State('stop', self.enterStop, self.exitStop, ['walk', 'died', 'teleportOut', 'doorIn']), State('doorIn', self.enterDoorIn, self.exitDoorIn, ['stop']), State('doorOut', self.enterDoorOut, self.exitDoorOut, ['walk']), State('final', self.enterFinal, self.exitFinal, ['final'])], 'start', 'final') def enter(self, requestStatus): Place.Place.enter(self) self.fsm.enterInitialState() base.playMusic(self.loader.interiorMusic, volume=0.8, looping=1) self.fsm.request(requestStatus['how'], [requestStatus]) def exit(self): self.loader.interiorMusic.stop() Place.Place.exit(self) def load(self): Place.Place.load(self) self.parentFSM.getStateNamed('toonInterior').addChild(self.fsm) def unload(self): self.parentFSM.getStateNamed('toonInterior').removeChild(self.fsm) del self.fsm del self.parentFSM self.ignoreAll() Place.Place.unload(self)
class Street(Place): notify = directNotify.newCategory("Street") def __init__(self, loader, parentFSM, doneEvent): self.parentFSM = parentFSM Place.__init__(self, loader, doneEvent) self.fsm = ClassicFSM('Street', [ State( 'start', self.enterStart, self.exitStart, ['walk', 'doorOut', 'teleportIn', 'tunnelOut', 'elevatorIn']), State('walk', self.enterWalk, self.exitWalk, ['stop', 'tunnelIn', 'shtickerBook', 'teleportOut']), State('shtickerBook', self.enterShtickerBook, self.exitShtickerBook, ['teleportOut', 'walk']), State('teleportOut', self.enterTeleportOut, self.exitTeleportOut, ['teleportIn', 'stop']), State('tunnelOut', self.enterTunnelOut, self.exitTunnelOut, ['walk']), State('tunnelIn', self.enterTunnelIn, self.exitTunnelIn, ['stop']), State('stop', self.enterStop, self.exitStop, ['walk', 'died', 'teleportOut', 'doorIn']), State('doorIn', self.enterDoorIn, self.exitDoorIn, ['stop']), State('doorOut', self.enterDoorOut, self.exitDoorOut, ['walk']), State('teleportIn', self.enterTeleportIn, self.exitTeleportIn, ['walk', 'stop']), State('elevatorIn', self.enterElevatorIn, self.exitElevatorIn, ['walk', 'stop']), State('final', self.enterFinal, self.exitFinal, ['final']) ], 'start', 'final') def enterElevatorIn(self, requestStatus): taskMgr.add(self.elevatorInTask, 'Street.elevatorInTask', extraArgs=[requestStatus['bldgDoId']], appendTask=True) def elevatorInTask(self, bldgDoId, task): bldg = base.cr.doId2do.get(bldgDoId) if bldg: if bldg.elevatorNodePath is not None: if self._enterElevatorGotElevator(): return task.done return task.cont def _enterElevatorGotElevator(self): if not messenger.whoAccepts('insideVictorElevator'): return False messenger.send('insideVictorElevator') return True def exitElevatorIn(self): taskMgr.remove('Street.elevatorInTask') def enter(self, requestStatus, visibilityFlag=1): Place.enter(self) self.fsm.enterInitialState() base.playMusic(self.loader.music, volume=0.8, looping=1) self.loader.geom.reparentTo(render) if visibilityFlag: self.visibilityOn() self.loader.hood.startSky() self.enterZone(requestStatus['zoneId']) self.fsm.request(requestStatus['how'], [requestStatus]) return def exit(self, vis=1): if vis: self.visibilityOff() self.loader.geom.reparentTo(hidden) self.loader.hood.stopSky() self.loader.music.stop() Place.exit(self) def load(self): Place.load(self) self.parentFSM.getStateNamed('street').addChild(self.fsm) def unload(self): self.parentFSM.getStateNamed('street').removeChild(self.fsm) del self.fsm del self.parentFSM self.enterZone(None) self.ignoreAll() Place.unload(self) return def hideAllVisibles(self): for i in self.loader.nodeList: i.stash() def showAllVisibles(self): for i in self.loader.nodeList: i.unstash() def visibilityOn(self): self.hideAllVisibles() self.accept('on-floor', self.enterZone) def visibilityOff(self): self.ignore('on-floor') self.showAllVisibles() def enterZone(self, newZone): if isinstance(newZone, CollisionEntry): try: newZoneId = int(newZone.getIntoNode().getName()) except: self.notify.warning( 'Invalid floor collision node in street: %s' % newZone.getIntoNode().getName()) return else: newZoneId = newZone self.doEnterZone(newZoneId) def doEnterZone(self, newZoneId): visualizeZones = 0 if self.zoneId != None: for i in self.loader.nodeDict[self.zoneId]: if newZoneId: if i not in self.loader.nodeDict[newZoneId]: self.loader.fadeOutDict[i].start() else: i.stash() if newZoneId != None: for i in self.loader.nodeDict[newZoneId]: if self.zoneId: if i not in self.loader.nodeDict[self.zoneId]: self.loader.fadeInDict[i].start() else: if self.loader.fadeOutDict[i].isPlaying(): self.loader.fadeOutDict[i].finish() if self.loader.fadeInDict[i].isPlaying(): self.loader.fadeInDict[i].finish() i.unstash() if newZoneId != self.zoneId: if visualizeZones: if self.zoneId != None: self.loader.zoneDict[self.zoneId].clearColor() if newZoneId != None: self.loader.zoneDict[newZoneId].setColor(0, 0, 1, 1, 100) if newZoneId is not None: loader = base.cr.playGame.getPlace().loader if newZoneId in loader.zoneVisDict: base.cr.sendSetZoneMsg(newZoneId, loader.zoneVisDict[newZoneId]) else: visList = [newZoneId] + loader.zoneVisDict.values()[0] base.cr.sendSetZoneMsg(newZoneId, visList) self.zoneId = newZoneId geom = base.cr.playGame.getPlace().loader.geom return
class RaceGameMovement(DirectObject): MINIMUM_POWER = 0.3 MINIMUM_KEY_DELAY = 0.015 POWER_FACTOR = 2.5 defaultBoostBarColor = (0.4, 0.4, 0.7, 1.0) fullBoostBarColor = (0.0, 0.0, 0.7, 1.0) def __init__(self, avatar): DirectObject.__init__(self) self.avatar = avatar self.power = self.MINIMUM_POWER self.boost = 0.0 self.fsm = ClassicFSM('RaceGameMovement', [State('off', self.enterOff, self.exitOff, ['run']), State('run', self.enterRun, self.exitRun, ['fall', 'off']), State('fall', self.enterFall, self.exitFall, ['run', 'off']), State('final', self.enterFinal, self.exitFinal)], 'off', 'final') self.fsm.enterInitialState() self.boostFSM = ClassicFSM('Boost', [State('off', self.enterBoostOff, self.exitBoostOff, ['boost']), State('boost', self.enterBoost, self.exitBoost)], 'off', 'off') self.boostFSM.enterInitialState() self.keysPressed = {'arrow_left': 0, 'arrow_right': 0} self.startTime = 0.0 self.endTime = 0.0 self.fallTrack = None self.isStopped = True self.isBoosting = False return def setBoosting(self, value): self.isBoosting = value def getBoosting(self): return self.isBoosting def enterBoostOff(self): self.ignore('control') def exitBoostOff(self): pass def createGui(self): """ Create the GUI that will tell the client how much running power they have. """ self.powerFrame = DirectFrame() self.powerBg = OnscreenImage(image=DGG.getDefaultDialogGeom(), scale=(0.5, 1.0, 0.5), pos=(1.02, 0, 0.7), parent=self.powerFrame, color=CIGlobals.DialogColor) self.powerBar = DirectWaitBar(barColor=(0, 0.7, 0, 1), range=20.0, value=0, parent=self.powerFrame, scale=(0.15, 0, 1.1), pos=(1.02, 0, 0.66)) self.powerBar.setR(-90) self.powerTitle = DirectLabel(text='POWER', text_scale=0.08, pos=(1.02, 0, 0.85), relief=None, parent=self.powerFrame, text_fg=(1, 1, 0, 1), text_font=CIGlobals.getMickeyFont()) self.boostFrame = DirectFrame() self.boostBg = OnscreenImage(image=DGG.getDefaultDialogGeom(), scale=(0.5, 1.0, 0.5), pos=(0.45, 0, 0.7), parent=self.boostFrame, color=CIGlobals.DialogColor) self.boostBar = DirectWaitBar(barColor=self.defaultBoostBarColor, range=10, value=0, parent=self.boostFrame, scale=(0.15, 0, 1.1), pos=(0.45, 0, 0.66)) self.boostBar.setR(-90) self.boostTitle = DirectLabel(text='BOOST', text_scale=0.08, pos=(0.45, 0, 0.85), relief=None, parent=self.boostFrame, text_fg=(1, 1, 0, 1), text_font=CIGlobals.getMickeyFont()) self.boostFullLbl = DirectLabel(text='BOOST READY', text_scale=0.065, pos=(0.45, 0, 0.3), relief=None, parent=self.boostFrame, text_fg=self.fullBoostBarColor, text_shadow=(0.4, 0.4, 0.4, 1.0), text_font=CIGlobals.getToonFont()) self.boostFullLbl.hide() return def deleteGui(self): """ Delete the GUI that will tell the client how much running power they have. """ self.powerFrame.destroy() self.powerBg.destroy() self.powerBar.destroy() self.powerTitle.destroy() self.boostFrame.destroy() self.boostBg.destroy() self.boostBar.destroy() self.boostTitle.destroy() self.boostFullLbl.destroy() def enableArrowKeys(self): """ Enable the arrow keys to increase movement power. """ self.accept('arrow_left', self.keyPressed, ['arrow_left']) self.accept('arrow_right', self.keyPressed, ['arrow_right']) def disableArrowKeys(self): """ Disable the arrow keys to increase movement power. """ self.ignore('arrow_left') self.ignore('arrow_right') def boostKeyPressed(self): self.boostFullLbl.hide() self.boostFSM.request('boost') def keyPressed(self, key): """ Figure out which key was pressed and increment the movement power if the values of both keys are 1. Also, make the avatar fall down if the time between key presses is too fast or the avatar pressed the same key more than once.""" self.stopDelayTimer() if self.keysPressed[key] == 1 or self.isTooFast(): self.resetKeys() self.fsm.request('fall') return self.keysPressed[key] = 1 if self.keysPressed['arrow_left'] == 1 and self.keysPressed['arrow_right'] == 1: self.resetKeys() self.changePower() self.restartDelayTimer() def enterBoost(self): self.disableArrowKeys() self.resetKeys() base.localAvatar.b_setAnimState('swim') self.power = 30.0 taskMgr.add(self.boostTask, 'boostTask') self.boostSfx = base.loadSfx('phase_6/audio/sfx/KART_turboLoop.wav') base.playSfx(self.boostSfx, looping=1) def exitBoost(self): self.enableArrowKeys() base.localAvatar.b_setAnimState('run') self.power = 17.0 taskMgr.remove('boostTask') self.boostSfx.stop() del self.boostSfx def boostTask(self, task): if self.boostBar['value'] <= 0.0: self.boostFSM.request('off') self.boostBar['barColor'] = self.defaultBoostBarColor return task.done self.boostBar['value'] -= 0.3 task.delayTime = 0.05 return task.again def enterFall(self): """ The avatar is pressing his arrow keys too fast. Stop running and make the avatar fall down. """ self.avatar.b_setAnimState('fallFWD') self.fallTrack = Sequence(Wait(2.5), Func(self.fsm.request, 'run')) self.fallTrack.start() def exitFall(self): self.fallTrack.pause() self.fallTrack = None return def isTooFast(self): """ Determine if the delay between key presses in seconds is too low. """ return self.getDelayTime() < self.MINIMUM_KEY_DELAY def resetKeys(self): """ Reset the value of the keys. """ for key in self.keysPressed: self.keysPressed[key] = 0 def changePower(self): """ Increase the avatar's movement power. """ self.power = self.POWER_FACTOR / self.getDelayTime() if self.boostBar['barColor'] != self.fullBoostBarColor: if self.power >= self.powerBar['range']: self.boostBar['value'] += 0.8 if self.boostBar['value'] >= self.boostBar['range']: self.boostBar['barColor'] = self.fullBoostBarColor self.boostFullLbl.show() self.acceptOnce('control', self.boostKeyPressed) print self.power self.powerBar.update(self.power) def startDelayTimer(self): self.startTime = globalClock.getFrameTime() def stopDelayTimer(self): self.endTime = globalClock.getFrameTime() def resetDelayTimer(self): self.startTime = 0.0 self.endTime = 0.0 def restartDelayTimer(self): self.stopDelayTimer() self.resetDelayTimer() self.startDelayTimer() def getDelayTime(self): return self.endTime - self.startTime def enterRun(self): """ Start moving the avatar, make the avatar run, and start tracking the delay between key presses. """ taskMgr.add(self.move, 'move') if self.boostBar['barColor'] == self.fullBoostBarColor: self.boostFullLbl.show() self.acceptOnce('control', self.boostKeyPressed) self.startDelayTimer() self.enableArrowKeys() self.avatar.b_setAnimState('run') self.isStopped = False def exitRun(self): """ Stop moving the avatar, make the avatar stand, and stop tracking the delay between key presses. """ taskMgr.remove('move') self.boostFSM.request('off') if self.boostBar['barColor'] == self.fullBoostBarColor: self.boostFullLbl.hide() self.ignore('control') self.stopDelayTimer() self.resetDelayTimer() self.disableArrowKeys() self.avatar.b_setAnimState('neutral') self.isStopped = True self.power = self.MINIMUM_POWER self.powerBar.update(0) def enterOff(self): pass def exitOff(self): pass def enterFinal(self): pass def exitFinal(self): pass def decreasePower(self, task): """ Decrease power so the avatar does not keep the same amount of power while not tapping the arrow keys. """ if self.power > self.MINIMUM_POWER: self.power -= self.POWER_FACTOR / 0.01 if self.power < self.MINIMUM_POWER: self.power = self.MINIMUM_POWER task.delayTime = 0.5 return Task.again def move(self, task): """ Move the avatar forward on the Y axis with the current amount of power. """ dt = globalClock.getDt() self.avatar.setY(self.avatar.getY() + self.power * dt) return Task.cont def cleanup(self): self.fsm.requestFinalState()
class PlayGame(StateData): notify = directNotify.newCategory('PlayGame') Hood2HoodClass = {ZoneUtil.ToontownCentral: TTHood.TTHood, ZoneUtil.MinigameArea: MGHood.MGHood, ZoneUtil.TheBrrrgh: BRHood.BRHood, ZoneUtil.DonaldsDreamland: DLHood.DLHood, ZoneUtil.MinniesMelodyland: MLHood.MLHood, ZoneUtil.DaisyGardens: DGHood.DGHood, ZoneUtil.DonaldsDock: DDHood.DDHood, ZoneUtil.BattleTTC: CTCHood.CTCHood, ZoneUtil.CogTropolis: CTHood.CTHood} Hood2HoodState = {ZoneUtil.ToontownCentral: 'TTHood', ZoneUtil.MinigameArea: 'MGHood', ZoneUtil.TheBrrrgh: 'BRHood', ZoneUtil.DonaldsDreamland: 'DLHood', ZoneUtil.MinniesMelodyland: 'MLHood', ZoneUtil.DaisyGardens: 'DGHood', ZoneUtil.DonaldsDock: 'DDHood', ZoneUtil.BattleTTC: 'CTCHood', ZoneUtil.CogTropolis: 'CTHood'} def __init__(self, parentFSM, doneEvent): StateData.__init__(self, "playGameDone") self.doneEvent = doneEvent self.fsm = ClassicFSM('World', [State('off', self.enterOff, self.exitOff, ['quietZone']), State('quietZone', self.enterQuietZone, self.exitQuietZone, ['TTHood', 'BRHood', 'DLHood', 'MLHood', 'DGHood', 'DDHood', 'MGHood', 'CTCHood', 'CTHood']), State('TTHood', self.enterTTHood, self.exitTTHood, ['quietZone']), State('BRHood', self.enterBRHood, self.exitBRHood, ['quietZone']), State('DLHood', self.enterDLHood, self.exitDLHood, ['quietZone']), State('MLHood', self.enterMLHood, self.exitMLHood, ['quietZone']), State('DGHood', self.enterDGHood, self.exitDGHood, ['quietZone']), State('DDHood', self.enterDDHood, self.exitDDHood, ['quietZone']), State('MGHood', self.enterMGHood, self.exitMGHood, ['quietZone']), State('CTCHood', self.enterCTCHood, self.exitCTCHood, ['quietZone']), State('CTHood', self.enterCTHood, self.exitCTHood, ['quietZone'])], 'off', 'off') self.fsm.enterInitialState() self.parentFSM = parentFSM self.parentFSM.getStateNamed('playGame').addChild(self.fsm) self.hoodDoneEvent = 'hoodDone' self.hood = None self.quietZoneDoneEvent = uniqueName('quietZoneDone') self.quietZoneStateData = None self.place = None self.lastHood = None self.suitManager = None def enter(self, hoodId, zoneId, avId): StateData.enter(self) whereName = ZoneUtil.getWhereName(zoneId) loaderName = ZoneUtil.getLoaderName(zoneId) self.fsm.request('quietZone', [{'zoneId': zoneId, 'hoodId': hoodId, 'where': whereName, 'how': 'teleportIn', 'avId': avId, 'shardId': None, 'loader': loaderName}]) def exit(self): StateData.exit(self) def getCurrentWorldName(self): return self.fsm.getCurrentState().getName() def enterOff(self): pass def exitOff(self): pass def enterCTHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitCTHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.CogTropolis def enterCTCHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitCTCHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.ToontownCentral def enterDDHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitDDHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.DonaldsDock def enterDGHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitDGHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.DaisyGardens def enterMLHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitMLHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.MinniesMelodyland def enterDLHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitDLHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.DonaldsDreamland def enterBRHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitBRHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.TheBrrrgh def enterTTHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitTTHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.ToontownCentral def enterMGHood(self, requestStatus): self.accept(self.hoodDoneEvent, self.handleHoodDone) self.hood.enter(requestStatus) def exitMGHood(self): self.ignore(self.hoodDoneEvent) self.hood.exit() self.hood.unload() self.hood = None self.lastHood = ZoneUtil.MinigameArea def handleHoodDone(self): doneStatus = self.hood.getDoneStatus() if doneStatus['zoneId'] is None: self.doneStatus = doneStatus messenger.send(self.doneEvent) else: self.fsm.request('quietZone', [doneStatus]) def loadDNAStore(self): if hasattr(self, 'dnaStore'): self.dnaStore.reset_nodes() self.dnaStore.reset_hood_nodes() self.dnaStore.reset_place_nodes() self.dnaStore.reset_hood() self.dnaStore.reset_fonts() self.dnaStore.reset_DNA_vis_groups() self.dnaStore.reset_materials() self.dnaStore.reset_block_numbers() self.dnaStore.reset_block_zones() self.dnaStore.reset_suit_points() del self.dnaStore self.dnaStore = DNAStorage() loadDNAFile(self.dnaStore, 'phase_4/dna/storage.pdna') self.dnaStore.storeFont('humanist', CIGlobals.getToonFont()) self.dnaStore.storeFont('mickey', CIGlobals.getMickeyFont()) self.dnaStore.storeFont('suit', CIGlobals.getSuitFont()) loadDNAFile(self.dnaStore, 'phase_3.5/dna/storage_interior.pdna') def enterQuietZone(self, requestStatus): self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone, [requestStatus]) self.acceptOnce('enteredQuietZone', self.handleEnteredQuietZone, [requestStatus]) self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent, 0) self.quietZoneStateData.load() self.quietZoneStateData.enter(requestStatus) def handleEnteredQuietZone(self, requestStatus): hoodId = requestStatus['hoodId'] if self.Hood2HoodClass.has_key(hoodId): hoodClass = self.Hood2HoodClass[hoodId] base.transitions.noTransitions() loader.beginBulkLoad('hood', hoodId, 100) self.loadDNAStore() self.hood = hoodClass(self.fsm, self.hoodDoneEvent, self.dnaStore, hoodId) self.hood.load() hoodState = self.Hood2HoodState[hoodId] self.fsm.request(hoodState, [requestStatus], exitCurrent = 0) self.quietZoneStateData.fsm.request('waitForSetZoneResponse') def handleQuietZoneDone(self, requestStatus): if self.hood: self.hood.enterTheLoader(requestStatus) self.hood.loader.enterThePlace(requestStatus) loader.endBulkLoad('hood') self.exitQuietZone() def exitQuietZone(self): if self.quietZoneStateData: self.ignore('enteredQuietZone') self.ignore(self.quietZoneDoneEvent) self.quietZoneStateData.exit() self.quietZoneStateData.unload() self.quietZoneStateData = None def setPlace(self, place): self.place = place def getPlace(self): return self.place
class Suit(Avatar.Avatar): healthColors = (Vec4(0, 1, 0, 1), Vec4(1, 1, 0, 1), Vec4(1, 0.5, 0, 1), Vec4(1, 0, 0, 1), Vec4(0.3, 0.3, 0.3, 1)) healthGlowColors = (Vec4(0.25, 1, 0.25, 0.5), Vec4(1, 1, 0.25, 0.5), Vec4(1, 0.5, 0.25, 0.5), Vec4(1, 0.25, 0.25, 0.5), Vec4(0.3, 0.3, 0.3, 0)) medallionColors = {'c': Vec4(0.863, 0.776, 0.769, 1.0), 's': Vec4(0.843, 0.745, 0.745, 1.0), 'l': Vec4(0.749, 0.776, 0.824, 1.0), 'm': Vec4(0.749, 0.769, 0.749, 1.0)} health2DmgMultiplier = 2.5 def __init__(self): try: self.Suit_initialized return except: self.Suit_initialized = 1 Avatar.Avatar.__init__(self) self.avatarType = CIGlobals.Suit self.name = '' self.chat = '' self.suit = None self.suitHeads = None self.suitHead = None self.loserSuit = None self.healthMeterGlow = None self.healthMeter = None self.weapon = None self.weapon_sfx = None self.anim = None self.suit_dial = None self.shadow = None self.balloon_sfx = None self.add_sfx = None self.explosion = None self.largeExp = None self.smallExp = None self.death_sfx = None self.attack = None self.wtrajectory = None self.throwObjectId = None self.hasSpawned = False self.condition = 0 self.type = "" self.head = "" self.team = "" self.isSkele = 0 self.animFSM = ClassicFSM('Suit', [State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('walk', self.enterWalk, self.exitWalk), State('die', self.enterDie, self.exitDie), State('attack', self.enterAttack, self.exitAttack), State('flydown', self.enterFlyDown, self.exitFlyDown), State('pie', self.enterPie, self.exitPie), State('win', self.enterWin, self.exitWin), State('flyaway', self.enterFlyAway, self.exitFlyAway), State('rollodex', self.enterRollodex, self.exitRollodex)], 'off', 'off') animStateList = self.animFSM.getStates() self.animFSM.enterInitialState() self.initializeBodyCollisions() def delete(self): try: self.Suit_deleted except: self.Suit_deleted = 1 if self.suit: self.cleanupSuit() if self.loserSuit: self.cleanupLoserSuit() if self.suitHeads: self.suitHeads.remove() self.suitHeads = None if self.suitHead: self.suitHead.remove() self.suitHead = None if self.healthMeterGlow: self.healthMeterGlow.remove() self.healthMeterGlow = None if self.healthMeter: self.healthMeter.remove() self.healthMeter = None if self.shadow: self.shadow.remove() self.shadow = None self.weapon = None self.weapon_sfx = None self.suit_dial = None del self.shadowPlacer def generateSuit(self, suitType, suitHead, suitTeam, suitHealth, skeleton): self.health = suitHealth self.maxHealth = suitHealth self.generateBody(suitType, suitTeam, suitHead, skeleton) self.generateHealthMeter() self.generateHead(suitType, suitHead) self.setupNameTag() Avatar.Avatar.initShadow(self) def generateBody(self, suitType, suitTeam, suitHead, skeleton): if self.suit: self.cleanupSuit() self.team = suitTeam self.type = suitType self.head = suitHead self.isSkele = skeleton if suitType == "A": if skeleton: self.suit = Actor("phase_5/models/char/cogA_robot-zero.bam") else: self.suit = Actor("phase_3.5/models/char/suitA-mod.bam") self.suit.loadAnims({"neutral": "phase_4/models/char/suitA-neutral.bam", "walk": "phase_4/models/char/suitA-walk.bam", "pie": "phase_4/models/char/suitA-pie-small.bam", "land": "phase_5/models/char/suitA-landing.bam", "throw-object": "phase_5/models/char/suitA-throw-object.bam", "throw-paper": "phase_5/models/char/suitA-throw-paper.bam", "glower": "phase_5/models/char/suitA-glower.bam", "win": "phase_4/models/char/suitA-victory.bam", "rollodex": "phase_5/models/char/suitA-roll-o-dex.bam"}) if suitType == "B": if skeleton: self.suit = Actor("phase_5/models/char/cogB_robot-zero.bam") else: self.suit = Actor("phase_3.5/models/char/suitB-mod.bam") self.suit.loadAnims({"neutral": "phase_4/models/char/suitB-neutral.bam", "walk": "phase_4/models/char/suitB-walk.bam", "pie": "phase_4/models/char/suitB-pie-small.bam", "land": "phase_5/models/char/suitB-landing.bam", "throw-object": "phase_5/models/char/suitB-throw-object.bam", "throw-paper": "phase_5/models/char/suitB-throw-paper.bam", "glower": "phase_5/models/char/suitB-magic1.bam", "win": "phase_4/models/char/suitB-victory.bam", "rollodex": "phase_5/models/char/suitB-roll-o-dex.bam"}) if suitType == "C": if skeleton: self.suit = Actor("phase_5/models/char/cogC_robot-zero.bam") else: self.suit = Actor("phase_3.5/models/char/suitC-mod.bam") self.suit.loadAnims({"neutral": "phase_3.5/models/char/suitC-neutral.bam", "walk": "phase_3.5/models/char/suitC-walk.bam", "pie": "phase_3.5/models/char/suitC-pie-small.bam", "land": "phase_5/models/char/suitC-landing.bam", "throw-object": "phase_3.5/models/char/suitC-throw-paper.bam", "throw-paper": "phase_3.5/models/char/suitC-throw-paper.bam", "glower": "phase_5/models/char/suitC-glower.bam", "win": "phase_4/models/char/suitC-victory.bam"}) if skeleton: self.suit.setTwoSided(1) self.suit.getGeomNode().setScale(CIGlobals.SuitScales[suitHead] / CIGlobals.SuitScaleFactors[suitType]) if skeleton: if suitTeam == "s": self.suit_tie = loader.loadTexture("phase_5/maps/cog_robot_tie_sales.jpg") elif suitTeam == "m": self.suit_tie = loader.loadTexture("phase_5/maps/cog_robot_tie_money.jpg") elif suitTeam == "l": self.suit_tie = loader.loadTexture("phase_5/maps/cog_robot_tie_legal.jpg") elif suitTeam == "c": self.suit_tie = loader.loadTexture("phase_5/maps/cog_robot_tie_boss.jpg") self.suit.find('**/tie').setTexture(self.suit_tie, 1) else: self.suit_blazer = loader.loadTexture("phase_3.5/maps/" + suitTeam + "_blazer.jpg") self.suit_leg = loader.loadTexture("phase_3.5/maps/" + suitTeam + "_leg.jpg") self.suit_sleeve = loader.loadTexture("phase_3.5/maps/" + suitTeam + "_sleeve.jpg") self.suit.find('**/legs').setTexture(self.suit_leg, 1) self.suit.find('**/arms').setTexture(self.suit_sleeve, 1) self.suit.find('**/torso').setTexture(self.suit_blazer, 1) if suitHead == "coldcaller": self.suit.find('**/hands').setColor(0.55, 0.65, 1.0, 1.0) elif suitHead == "corporateraider": self.suit.find('**/hands').setColor(0.85, 0.55, 0.55, 1.0) elif suitHead == "bigcheese": self.suit.find('**/hands').setColor(0.75, 0.95, 0.75, 1.0) elif suitHead == "bloodsucker": self.suit.find('**/hands').setColor(0.95, 0.95, 1.0, 1.0) elif suitHead == "spindoctor": self.suit.find('**/hands').setColor(0.5, 0.8, 0.75, 1.0) elif suitHead == "legaleagle": self.suit.find('**/hands').setColor(0.25, 0.25, 0.5, 1.0) elif suitHead == "pennypincher": self.suit.find('**/hands').setColor(1.0, 0.5, 0.6, 1.0) elif suitHead == "loanshark": self.suit.find('**/hands').setColor(0.5, 0.85, 0.75, 1.0) else: self.suit.find('**/hands').setColor(CIGlobals.SuitHandColors[suitTeam]) self.suit.reparentTo(self) def generateHead(self, suitType, suitHead): if self.suitHead: self.cleanupSuitHead() self.type = suitType self.head = suitHead if suitHead == "vp": self.suitHead = Actor("phase_9/models/char/sellbotBoss-head-zero.bam", {"neutral": "phase_9/models/char/bossCog-head-Ff_neutral.bam"}) self.suitHead.setTwoSided(True) self.suitHead.loop("neutral") self.suitHead.setScale(0.35) self.suitHead.setHpr(270, 0, 270) self.suitHead.setZ(-0.10) else: if suitType == "A" or suitType == "B": self.suitHeads = loader.loadModel("phase_4/models/char/suit" + suitType + "-heads.bam") else: self.suitHeads = loader.loadModel("phase_3.5/models/char/suit" + suitType + "-heads.bam") self.suitHead = self.suitHeads.find('**/' + CIGlobals.SuitHeads[suitHead]) if suitHead == "flunky": glasses = self.suitHeads.find('**/glasses') glasses.reparentTo(self.suitHead) glasses.setTwoSided(True) if suitHead in CIGlobals.SuitSharedHeads: if suitHead == "coldcaller": self.suitHead.setColor(0.25, 0.35, 1.0, 1.0) else: headTexture = loader.loadTexture("phase_3.5/maps/" + suitHead + ".jpg") self.suitHead.setTexture(headTexture, 1) if not self.isSkele: self.suitHead.reparentTo(self.suit.find('**/joint_head')) def cleanupSuit(self): if self.shadow: self.shadow.remove() self.shadow = None self.removeHealthBar() self.suit.cleanup() self.suit = None def cleanupSuitHead(self): if self.suitHeads: self.suitHeads.remove() self.suitHeads = None if self.suitHead: self.suitHead.remove() self.suitHead = None def cleanupLoserSuit(self): if self.explosion: self.explosion.remove() self.explosion = None if self.smallExp: self.smallExp = None if self.largeExp: self.largeExp.cleanup() self.largeExp = None if self.loserSuit: self.loserSuit.cleanup() self.loserSuit = None def setName(self, nameString, charName): Avatar.Avatar.setName(self, nameString, avatarType=self.avatarType, charName=charName) def setChat(self, chatString): self.chat = chatString if self.isSkele: if "?" in chatString: self.suit_dial = audio3d.loadSfx("phase_5/audio/sfx/Skel_COG_VO_question.ogg") elif "!" in chatString: self.suit_dial = audio3d.loadSfx("phase_5/audio/sfx/Skel_COG_VO_grunt.ogg") else: self.suit_dial = audio3d.loadSfx("phase_5/audio/sfx/Skel_COG_VO_statement.ogg") elif self.head == "vp": if "?" in chatString: self.suit_dial = audio3d.loadSfx("phase_9/audio/sfx/Boss_COG_VO_question.ogg") elif "!" in chatString: self.suit_dial = audio3d.loadSfx("phase_9/audio/sfx/Boss_COG_VO_grunt.ogg") else: self.suit_dial = audio3d.loadSfx("phase_9/audio/sfx/Boss_COG_VO_statement.ogg") else: if "?" in chatString: self.suit_dial = audio3d.loadSfx("phase_3.5/audio/dial/COG_VO_question.ogg") elif "!" in chatString: self.suit_dial = audio3d.loadSfx("phase_3.5/audio/dial/COG_VO_grunt.ogg") else: self.suit_dial = audio3d.loadSfx("phase_3.5/audio/dial/COG_VO_statement.ogg") if self.isSkele: audio3d.attachSoundToObject(self.suit_dial, self.suit) else: audio3d.attachSoundToObject(self.suit_dial, self.suitHead) self.suit_dial.play() Avatar.Avatar.setChat(self, chatString) def generateHealthMeter(self): self.removeHealthBar() model = loader.loadModel("phase_3.5/models/gui/matching_game_gui.bam") button = model.find('**/minnieCircle') button.setScale(3.0) button.setH(180) button.setColor(self.healthColors[0]) chestNull = self.suit.find('**/def_joint_attachMeter') if chestNull.isEmpty(): chestNull = self.suit.find('**/joint_attachMeter') button.reparentTo(chestNull) self.healthBar = button glow = loader.loadModel("phase_3.5/models/props/glow.bam") glow.reparentTo(self.healthBar) glow.setScale(0.28) glow.setPos(-0.005, 0.01, 0.015) glow.setColor(self.healthGlowColors[0]) button.flattenLight() self.healthBarGlow = glow self.condition = 0 def updateHealthBar(self, hp): if hp > self.hp: self.hp = hp self.hp -= hp health = float(self.health) / float(self.maxHP) if health > 0.95: condition = 0 elif health > 0.7: condition = 1 elif health > 0.3: condition = 2 elif health > 0.05: condition = 3 elif health > 0.0: condition = 4 else: condition = 5 if self.condition != condition: if condition == 4: blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.75), Task(self.__blinkGray), Task.pause(0.1)) taskMgr.add(blinkTask, self.taskName('blink-task')) elif condition == 5: if self.condition == 4: taskMgr.remove(self.taskName('blink-task')) blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.25), Task(self.__blinkGray), Task.pause(0.1)) taskMgr.add(blinkTask, self.taskName('blink-task')) else: self.healthBar.setColor(self.healthColors[condition], 1) self.healthBarGlow.setColor(self.healthGlowColors[condition], 1) self.condition = condition def __blinkRed(self, task): self.healthBar.setColor(self.healthColors[3], 1) self.healthBarGlow.setColor(self.healthGlowColors[3], 1) if self.condition == 5: self.healthBar.setScale(1.17) return Task.done def __blinkGray(self, task): if not self.healthBar: return self.healthBar.setColor(self.healthColors[4], 1) self.healthBarGlow.setColor(self.healthGlowColors[4], 1) if self.condition == 5: self.healthBar.setScale(1.0) return Task.done def removeHealthBar(self): if self.healthMeter: self.healthBar.removeNode() self.healthBar = None if self.condition == 4 or self.condition == 5: taskMgr.remove(self.taskName('blink-task')) self.healthCondition = 0 return def enterOff(self): self.anim = None return def exitOff(self): pass def exitGeneral(self): self.suit.stop() def enterNeutral(self): self.suit.loop("neutral") def exitNeutral(self): self.exitGeneral() def enterRollodex(self): self.suit.play("rollodex") def exitRollodex(self): self.exitGeneral() def enterWalk(self): self.suit.loop("walk") def exitWalk(self): self.exitGeneral() def generateLoserSuit(self): self.cleanupLoserSuit() if self.type == "A": if self.isSkele: self.loserSuit = Actor("phase_5/models/char/cogA_robot-lose-mod.bam") else: self.loserSuit = Actor("phase_4/models/char/suitA-lose-mod.bam") self.loserSuit.loadAnims({"lose": "phase_4/models/char/suitA-lose.bam"}) if self.type == "B": if self.isSkele: self.loserSuit = Actor("phase_5/models/char/cogB_robot-lose-mod.bam") else: self.loserSuit = Actor("phase_4/models/char/suitB-lose-mod.bam") self.loserSuit.loadAnims({"lose": "phase_4/models/char/suitB-lose.bam"}) if self.type == "C": if self.isSkele: self.loserSuit = Actor("phase_5/models/char/cogC_robot-lose-mod.bam") else: self.loserSuit = Actor("phase_3.5/models/char/suitC-lose-mod.bam") self.loserSuit.loadAnims({"lose": "phase_3.5/models/char/suitC-lose.bam"}) if self.isSkele: self.loserSuit.find('**/tie').setTexture(self.suit_tie, 1) self.loserSuit.setTwoSided(1) else: self.loserSuit.find('**/hands').setColor(self.suit.find('**/hands').getColor()) self.loserSuit.find('**/legs').setTexture(self.suit_leg, 1) self.loserSuit.find('**/arms').setTexture(self.suit_sleeve, 1) self.loserSuit.find('**/torso').setTexture(self.suit_blazer, 1) self.loserSuit.getGeomNode().setScale(self.suit.getScale()) self.loserSuit.reparentTo(self) if not self.isSkele: self.suitHead.reparentTo(self.loserSuit.find('**/joint_head')) self.loserSuit.setPos(self.suit.getPos(render)) self.loserSuit.setHpr(self.suit.getHpr(render)) self.cleanupSuit() Avatar.Avatar.initShadow(self, self.avatarType) self.loserSuit.reparentTo(render) def enterDie(self): self.generateLoserSuit() self.state = "dead" self.loserSuit.play("lose") spinningSound = base.loadSfx("phase_3.5/audio/sfx/Cog_Death.ogg") deathSound = base.loadSfx("phase_3.5/audio/sfx/ENC_cogfall_apart.ogg") #audio3d.attachSoundToObject(spinningSound, self.loserSuit) #audio3d.attachSoundToObject(deathSound, self.loserSuit) Sequence(Wait(0.8), SoundInterval(spinningSound, duration=1.2, startTime=1.5, volume=0.4, node=self.loserSuit), SoundInterval(spinningSound, duration=3.0, startTime=0.6, volume=2.0, node=self.loserSuit), SoundInterval(deathSound, volume=0.32, node=self.loserSuit)).start() Sequence(Wait(0.8), Func(self.smallDeathParticles), Wait(4.2), Func(self.suitExplode), Wait(1.0), Func(self.delSuit)).start() def smallDeathParticles(self): self.smallExp = ParticleLoader.loadParticleEffect("phase_3.5/etc/gearExplosionSmall.ptf") self.smallExp.start(self.loserSuit) def suitExplode(self): self.smallExp.cleanup() self.largeExp = ParticleLoader.loadParticleEffect("phase_3.5/etc/gearExplosion.ptf") self.largeExp.start(self.loserSuit) self.explosion = loader.loadModel("phase_3.5/models/props/explosion.bam") self.explosion.setScale(0.5) self.explosion.reparentTo(render) self.explosion.setBillboardPointEye() if self.isSkele: self.explosion.setPos(self.loserSuit.find('**/joint_head').getPos(render) + (0, 0, 2)) else: self.explosion.setPos(self.suitHead.getPos(render) + (0,0,2)) def delSuit(self): self.cleanupLoserSuit() self.disableBodyCollisions() def exitDie(self): pass def enterFlyDown(self): self.fd_sfx = audio3d.loadSfx("phase_5/audio/sfx/ENC_propeller_in.ogg") self.prop = Actor("phase_4/models/props/propeller-mod.bam", {"chan": "phase_4/models/props/propeller-chan.bam"}) audio3d.attachSoundToObject(self.fd_sfx, self.prop) self.fd_sfx.play() self.prop.reparentTo(self.suit.find('**/joint_head')) propTrack = Sequence(Func(self.prop.loop, 'chan', fromFrame=0, toFrame=3), Wait(1.75), Func(self.prop.play, 'chan', fromFrame=3)) propTrack.start() if not self.hasSpawned: showSuit = Task.sequence(Task(self.hideSuit), Task.pause(0.3), Task(self.showSuit)) taskMgr.add(showSuit, "showsuit") self.hasSpawned = True dur = self.suit.getDuration('land') suitTrack = Sequence(Func(self.suit.pose, 'land', 0), Wait(1.9), ActorInterval(self.suit, 'land', duration=dur)) suitTrack.start() def hideSuit(self, task): self.hide() return Task.done def showSuit(self, task): self.show() fadeIn = Sequence(Func(self.setTransparency, 1), self.colorScaleInterval(0.6, colorScale=Vec4(1,1,1,1), startColorScale=Vec4(1,1,1,0)), Func(self.clearColorScale), Func(self.clearTransparency), Func(self.reparentTo, render)) fadeIn.start() return Task.done def initializeLocalCollisions(self, name): Avatar.Avatar.initializeLocalCollisions(self, 1, 3, name) def initializeBodyCollisions(self): Avatar.Avatar.initializeBodyCollisions(self, self.avatarType, 2.25, 1, 4, 2) self.initializeRay(self.avatarType) self.collTube.setTangible(0) def deleteBean(self): if self.bean: self.bean.remove_node() self.bean = None def createJellyBean(self): self.deleteBean() money = int(self.maxHP / CIGlobals.SuitAttackDamageFactors['clipontie']) if money == 1: self.bean = loader.loadModel("phase_5.5/models/estate/jellyBean.bam") self.bean.set_two_sided(True) random_r = random.uniform(0, 1) random_g = random.uniform(0, 1) random_b = random.uniform(0, 1) self.bean.set_color(random_r, random_g, random_b, 1) else: self.bean = loader.loadModel("phase_5.5/models/estate/jellybeanJar.bam") self.bean.reparent_to(render) self.bean.set_pos(self.get_pos(render) + (0, 0, 1)) bean_int = self.bean.hprInterval(1, Point3(360, 0, 0), startHpr=(0, 0, 0)) bean_int.loop() def exitFlyDown(self): audio3d.detachSound(self.fd_sfx) self.prop.cleanup() self.prop = None def enterFlyAway(self): self.fa_sfx = audio3d.loadSfx("phase_5/audio/sfx/ENC_propeller_out.ogg") self.prop = Actor("phase_4/models/props/propeller-mod.bam", {"chan": "phase_4/models/props/propeller-chan.bam"}) audio3d.attachSoundToObject(self.fa_sfx, self.prop) self.fa_sfx.play() self.prop.reparentTo(self.suit.find('**/joint_head')) self.prop.setPlayRate(-1.0, "chan") propTrack = Sequence(Func(self.prop.play, 'chan', fromFrame=3), Wait(1.75), Func(self.prop.play, 'chan', fromFrame=0, toFrame=3)) propTrack.start() self.suit.setPlayRate(-1.0, 'land') self.suit.play('land') def exitFlyAway(self): audio3d.detachSound(self.fa_sfx) self.prop.cleanup() self.prop = None def enterAttack(self, attack): self.attack = attack self.weapon_state = 'start' if attack == "canned": self.weapon = loader.loadModel("phase_5/models/props/can.bam") self.weapon.setScale(15) self.weapon.setR(180) self.wss = CollisionSphere(0,0,0,0.05) elif attack == "clipontie": self.weapon = loader.loadModel("phase_5/models/props/power-tie.bam") self.weapon.setScale(4) self.weapon.setR(180) self.wss = CollisionSphere(0,0,0,0.2) elif attack == "sacked": self.weapon = loader.loadModel("phase_5/models/props/sandbag-mod.bam") self.weapon.setScale(2) self.weapon.setR(180) self.weapon.setP(90) self.weapon.setY(-2.8) self.weapon.setZ(-0.3) self.wss = CollisionSphere(0,0,0,1) elif attack == "playhardball": self.weapon = loader.loadModel("phase_5/models/props/baseball.bam") self.weapon.setScale(10) self.wss = CollisionSphere(0,0,0,0.1) self.weapon.setZ(-0.5) elif attack == "marketcrash": self.weapon = loader.loadModel("phase_5/models/props/newspaper.bam") self.weapon.setScale(3) self.weapon.setPos(0.41, -0.06, -0.06) self.weapon.setHpr(90, 0, 270) self.wss = CollisionSphere(0,0,0,0.35) elif attack == "glowerpower": self.weapon = loader.loadModel("phase_5/models/props/dagger.bam") self.wss = CollisionSphere(0,0,0,1) else: notify.warning("unknown attack!") self.throwObjectId = random.uniform(0, 101010101010) if attack == "canned" or attack == "playhardball": self.weapon.reparentTo(self.suit.find('**/joint_Rhold')) if self.type == "C": taskMgr.doMethodLater(2.2, self.throwObject, "throwObject" + str(self.throwObjectId)) else: taskMgr.doMethodLater(3, self.throwObject, "throwObject" + str(self.throwObjectId)) self.suit.play("throw-object") elif attack == "clipontie" or attack == "marketcrash" or attack == "sacked": self.weapon.reparentTo(self.suit.find('**/joint_Rhold')) if self.type == "C": taskMgr.doMethodLater(2.2, self.throwObject, "throwObject" + str(self.throwObjectId)) else: taskMgr.doMethodLater(3, self.throwObject, "throwObject" + str(self.throwObjectId)) self.suit.play("throw-paper") elif attack == "glowerpower": taskMgr.doMethodLater(1, self.throwObject, "throwObject" + str(self.throwObjectId)) self.suit.play("glower") self.weaponSensorId = random.uniform(0, 1010101010101001) wsnode = CollisionNode('weaponSensor' + str(self.weaponSensorId)) wsnode.addSolid(self.wss) self.wsnp = self.weapon.attachNewNode(wsnode) if attack == "sacked": self.wsnp.setZ(1) elif attack == "marketcrash": self.wsnp.setPos(-0.25, 0.3, 0) def delWeapon(self, task): if self.weapon: self.weapon.removeNode() self.weapon = None return task.done def interruptAttack(self): if self.wtrajectory: if self.wtrajectory.isStopped(): if self.weapon: self.weapon.removeNode() self.weapon = None if self.throwObjectId: taskMgr.remove("throwObject" + str(self.throwObjectId)) def handleWeaponTouch(self): if not self.attack == "glowerpower" or not self.attack == "clipontie": if self.weapon_sfx: self.weapon_sfx.stop() try: self.wtrajectory.pause() except: pass if self.weapon: self.weapon.removeNode() self.weapon = None def weaponCollisions(self): self.wsnp.setCollideMask(BitMask32(0)) self.wsnp.node().setFromCollideMask(CIGlobals.EventBitmask) event = CollisionHandlerEvent() event.setInPattern("%fn-into") event.setOutPattern("%fn-out") base.cTrav.addCollider(self.wsnp, event) def throwObject(self, task): self.playWeaponSound() self.weaponNP = NodePath("weaponNP") self.weaponNP.setScale(render, 1) try: self.weaponNP.reparentTo(self.find('**/joint_nameTag')) except: return task.done self.weaponNP.setPos(0, 50, 0) self.weaponNP.setHpr(0, 0, 0) if self.weapon: self.weapon.setScale(self.weapon.getScale(render)) try: self.weapon.reparentTo(render) except: return task.done self.weapon.setPos(0,0,0) self.weapon.setHpr(0,0,0) if self.attack == "glowerpower": self.weapon.setH(self.weaponNP.getH(render)) self.wtrajectory = self.weapon.posInterval(0.5, Point3(self.weaponNP.getPos(render)), startPos=(self.getX(render), self.getY(render) + 3, self.find('**/joint_head').getZ(render))) self.wtrajectory.start() else: self.wtrajectory = ProjectileInterval(self.weapon, startPos = (self.suit.find('**/joint_Rhold').getPos(render)), endPos = self.weaponNP.getPos(render), gravityMult = 0.7, duration = 1) self.wtrajectory.start() if self.attack == "glowerpower": taskMgr.doMethodLater(0.5, self.delWeapon, "delWeapon") else: taskMgr.doMethodLater(1, self.delWeapon, "delWeapon") self.weapon_state = 'released' def playWeaponSound(self): if self.attack == "glowerpower": self.weapon_sfx = audio3d.loadSfx("phase_5/audio/sfx/SA_glower_power.ogg") elif self.attack == "canned": self.weapon_sfx = audio3d.loadSfx("phase_5/audio/sfx/SA_canned_tossup_only.ogg") elif self.attack == "clipontie": self.weapon_sfx = audio3d.loadSfx("phase_5/audio/sfx/SA_powertie_throw.ogg") elif self.attack == "sacked": self.weapon_sfx = audio3d.loadSfx("phase_5/audio/sfx/SA_canned_tossup_only.ogg") elif self.attack == "playhardball": self.weapon_sfx = audio3d.loadSfx("phase_5/audio/sfx/SA_canned_tossup_only.ogg") elif self.attack == "marketcrash": self.weapon_sfx = audio3d.loadSfx("phase_5/audio/sfx/SA_canned_tossup_only.ogg") if self.weapon: audio3d.attachSoundToObject(self.weapon_sfx, self.weapon) self.weapon_sfx.play() def exitAttack(self): pass def enterPie(self): self.suit.play("pie") def exitPie(self): self.exitGeneral() def enterWin(self): self.suit.play("win") def exitWin(self): self.exitGeneral()
class Walk(StateData): notify = directNotify.newCategory('Walk') def __init__(self, doneEvent): StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('Walk', [State('off', self.enterOff, self.exitOff, ['walking', 'deadWalking']), State('walking', self.enterWalking, self.exitWalking), State('deadWalking', self.enterDeadWalking, self.exitDeadWalking)], 'off', 'off') self.fsm.enterInitialState() def load(self): pass def unload(self): del self.fsm def enter(self): base.localAvatar.startPosHprBroadcast() base.localAvatar.d_broadcastPositionNow() base.localAvatar.startBlink() base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.collisionsOn() base.localAvatar.enableAvatarControls() base.localAvatar.enablePicking() def exit(self): base.localAvatar.lastState = None self.fsm.request('off') base.localAvatar.enablePicking() base.localAvatar.disableAvatarControls() base.localAvatar.detachCamera() base.localAvatar.stopSmartCamera() base.localAvatar.stopPosHprBroadcast() base.localAvatar.stopBlink() base.localAvatar.collisionsOff() base.localAvatar.controlManager.placeOnFloor() return def enterOff(self): pass def exitOff(self): pass def enterWalking(self): if base.localAvatar.getHealth() > 0: base.localAvatar.startTrackAnimToSpeed() base.localAvatar.setWalkSpeedNormal() else: self.fsm.request('deadWalking') def exitWalking(self): base.localAvatar.stopTrackAnimToSpeed() def enterDeadWalking(self): base.localAvatar.startTrackAnimToSpeed() base.localAvatar.setWalkSpeedSlow() base.taskMgr.add(self.__watchForPositiveHP, base.localAvatar.uniqueName('watchforPositiveHP')) def __watchForPositiveHP(self, task): if base.localAvatar.getHealth() > 0: self.fsm.request('walking') return task.done return task.cont def exitDeadWalking(self): base.taskMgr.remove(base.localAvatar.uniqueName('watchforPositiveHP')) base.localAvatar.stopTrackAnimToSpeed()
class AvChooser(StateData): notify = directNotify.newCategory('AvChooser') def __init__(self, parentFSM): StateData.__init__(self, 'avChooseDone') self.avChooseFSM = ClassicFSM('avChoose', [ State('getToonData', self.enterGetToonData, self.exitGetToonData), State('avChoose', self.enterAvChoose, self.exitAvChoose), State('waitForToonDelResponse', self.enterWaitForToonDelResponse, self.exitWaitForToonDelResponse), State('off', self.enterOff, self.exitOff) ], 'off', 'off') self.avChooseFSM.enterInitialState() self.parentFSM = parentFSM self.parentFSM.getStateNamed('avChoose').addChild(self.avChooseFSM) self.pickAToon = None self.setAvatarsNone() return def enter(self): StateData.enter(self) base.transitions.noTransitions() self.avChooseFSM.request('getToonData') def exit(self): StateData.exit(self) self.setAvatarsNone() self.avChooseFSM.requestFinalState() def setAvatarsNone(self): self.avChoices = [] def enterOff(self): pass def exitOff(self): pass def enterGetToonData(self): self.acceptOnce(base.cr.csm.getSetAvatarsEvent(), self.handleToonData) base.cr.csm.d_requestAvatars() def handleToonData(self, avatarList): for av in avatarList: avId = av[0] dna = av[1] name = av[2] slot = av[3] choice = AvChoice(dna, name, slot, avId) self.avChoices.append(choice) self.avChooseFSM.request('avChoose') def exitGetToonData(self): self.ignore(base.cr.csm.getSetAvatarsEvent()) def enterAvChoose(self): if base.cr.holidayManager.getHoliday() == HolidayType.CHRISTMAS: base.cr.music.stop() base.cr.music = base.loadMusic(CIGlobals.getHolidayTheme()) base.cr.music.setLoop(True) base.cr.music.setVolume(0.75) base.cr.music.play() whisper = WhisperPopup(HolidayGlobals.CHRISTMAS_TIME, CIGlobals.getToonFont(), ChatGlobals.WTSystem) whisper.manage(base.marginManager) self.pickAToon = CharSelection(self) self.pickAToon.load() def enterWaitForToonDelResponse(self, avId): self.acceptOnce(base.cr.csm.getToonDeletedEvent(), self.handleDeleteToonResp) base.cr.csm.sendDeleteToon(avId) def exitWaitForToonDelResponse(self): self.ignore(base.cr.csm.getToonDeletedEvent()) def hasToonInSlot(self, slot): if self.getAvChoiceBySlot(slot) != None: return True return False return def getNameInSlot(self, slot): return self.getAvChoiceBySlot(slot).getName() def getNameFromAvId(self, avId): for avChoice in self.avChoices: if avChoice.getAvId() == avId: return avChoice.getName() def getAvChoiceBySlot(self, slot): for avChoice in self.avChoices: if avChoice.getSlot() == slot: return avChoice return def getHeadInfo(self, slot): dna = self.getAvChoiceBySlot(slot).getDNA() self.pickAToon.dna.setDNAStrand(dna) return [ self.pickAToon.dna.getGender(), self.pickAToon.dna.getAnimal(), self.pickAToon.dna.getHead(), self.pickAToon.dna.getHeadColor() ] def handleDeleteToonResp(self): base.cr.loginFSM.request('avChoose') def exitAvChoose(self): self.pickAToon.unload() self.pickAToon = None return
class DistributedPieTurret(DistributedAvatar, DistributedSmoothNode): notify = directNotify.newCategory('DistributedPieTurret') def __init__(self, cr): DistributedAvatar.__init__(self, cr) DistributedSmoothNode.__init__(self, cr) self.fsm = ClassicFSM( 'DistributedPieTurret', [ State('off', self.enterOff, self.exitOff), State('scan', self.enterScan, self.exitScan), State('shoot', self.enterShoot, self.exitShoot) ], 'off', 'off' ) self.fsm.enterInitialState() self.reloadTime = 0.25 self.cannon = None self.track = None self.owner = None self.gag = None self.readyGag = None self.hitGag = None self.explosion = None self.wallCollNode = None self.eventCollNode = None self.event = None self.suit = None self.eventId = None self.entities = [] self.upgradeID = None self.deathEvent = None def setOwner(self, avatar): self.owner = avatar def getOwner(self): return self.owner def setGag(self, upgradeId): gags = {0 : CIGlobals.WholeCreamPie, 1 : CIGlobals.WholeFruitPie, 2 : CIGlobals.BirthdayCake, 3 : CIGlobals.WeddingCake} self.gag = gags.get(upgradeId) if not self.readyGag: self.loadGagInTurret() def b_setGag(self, upgradeId): self.sendUpdate('setGag', [upgradeId]) self.setGag(upgradeId) self.upgradeID = upgradeId def getGag(self): return self.gag def getGagID(self): return self.upgradeID def generate(self): DistributedAvatar.generate(self) DistributedSmoothNode.generate(self) def announceGenerate(self): DistributedAvatar.announceGenerate(self) DistributedSmoothNode.announceGenerate(self) self.healthLabel.setScale(1.1) self.deathEvent = self.uniqueName('DistributedPieTurret-death') self.makeTurret() def disable(self): self.fsm.requestFinalState() del self.fsm # This should fix crashes related to Sequences. if self.track: self.track.pause() self.track = None # Cleanup entities. for ent in self.entities: ent.cleanup() self.entities = None # Get rid of explosions. if self.explosion: self.explosion.removeNode() self.explosion = None self.removeTurret() DistributedSmoothNode.disable(self) DistributedAvatar.disable(self) def showAndMoveHealthLabel(self): self.unstashHpLabel() self.stopMovingHealthLabel() moveTrack = LerpPosInterval(self.healthLabel, duration = 0.5, pos = Point3(0, 0, 5), startPos = Point3(0, 0, 0), blendType = 'easeOut') self.healthLabelTrack = Sequence(moveTrack, Wait(1.0), Func(self.stashHpLabel)) self.healthLabelTrack.start() # BEGIN STATES def enterShoot(self, suitId): if self.cannon: smoke = loader.loadModel("phase_4/models/props/test_clouds.bam") smoke.setBillboardPointEye() smoke.reparentTo(self.cannon.find('**/cannon')) smoke.setPos(0, 6, -3) smoke.setScale(0.5) smoke.wrtReparentTo(render) self.suit = self.cr.doId2do.get(suitId) self.cannon.find('**/cannon').lookAt(self.suit.find('**/joint_head')) self.cannon.find('**/square_drop_shadow').headsUp(self.suit.find('**/joint_head')) self.track = Sequence(Parallel(LerpScaleInterval(smoke, 0.5, 3), LerpColorScaleInterval(smoke, 0.5, Vec4(2, 2, 2, 0))), Func(smoke.removeNode)) self.track.start() self.createAndShootGag() def exitShoot(self): if hasattr(self, 'suit'): del self.suit def shoot(self, suitId): self.fsm.request('shoot', [suitId]) def scan(self, timestamp = None, afterShooting = 0): if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) self.fsm.request('scan', [ts, afterShooting]) def buildScanTrack(self, ts = None): if self.track: self.track.pause() self.track = None self.track = Parallel( Sequence( LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (60, 0, 0), startHpr = Vec3(-60, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (-60, 0, 0), startHpr = Vec3(60, 0, 0), blendType = 'easeInOut'), ), Sequence( LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (60, 0, 0), startHpr = Vec3(-60, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (-60, 0, 0), startHpr = Vec3(60, 0, 0), blendType = 'easeInOut'), ) ) if ts: self.track.loop(ts) else: self.track.loop() def enterScan(self, ts = 0, afterShooting = 0): if afterShooting: self.track = Parallel( LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (-60, 0, 0), startHpr = self.cannon.find('**/cannon').getHpr(), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (-60, 0, 0), startHpr = self.cannon.find('**/square_drop_shadow').getHpr(), blendType = 'easeInOut'), name = "afterShootTrack" + str(id(self)) ) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self._afterShootTrackDone) self.track.start(ts) else: self.buildScanTrack(ts) def exitScan(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None def enterOff(self): pass def exitOff(self): pass # END STATES def _afterShootTrackDone(self): self.buildScanTrack() def makeTurret(self): self.cannon = loader.loadModel('phase_4/models/minigames/toon_cannon.bam') self.cannon.reparentTo(self) self.loadGagInTurret() self.setupWallSphere() if self.isLocal(): self.setupEventSphere() def removeTurret(self): self.removeWallSphere() self.removeGagInTurret() if self.cannon: self.cannon.removeNode() self.cannon = None def getCannon(self): return self.cannon.find('**/cannon') def setupWallSphere(self): sphere = CollisionSphere(0.0, 0.0, 0.0, 3.0) node = CollisionNode('DistributedPieTurret.WallSphere') node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) self.wallCollNode = self.cannon.attachNewNode(node) self.wallCollNode.setZ(2) self.wallCollNode.setY(1.0) def removeWallSphere(self): if self.wallCollNode: self.wallCollNode.removeNode() self.wallCollNode = None def createAndShootGag(self): if not self.readyGag: self.loadGagInTurret() if self.readyGag: self.readyGag.shoot(Point3(0, 200, -90)) self.entities.append(self.readyGag) collideEventName = self.readyGag.getCollideEventName() self.readyGag = None if self.isLocal(): self.acceptOnce(collideEventName, self.handleGagCollision) Sequence(Wait(self.reloadTime), Func(self.loadGagInTurret)).start() def loadGagInTurret(self): if self.cannon and self.gag: self.removeGagInTurret() self.eventId = random.uniform(0, 100000000) self.readyGag = TurretGag(self, self.uniqueName('pieTurretCollision') + str(self.eventId), self.gag) self.readyGag.build() def removeGagInTurret(self): if self.readyGag: self.readyGag.cleanup() self.readyGag = None def makeSplat(self, index, pos): if index >= len(self.entities): return ent = self.entities[index] gagClass = ent.gagClass splat = gagClass.buildSplat(gagClass.splatScale, gagClass.splatColor) base.audio3d.attachSoundToObject(gagClass.hitSfx, splat) splat.reparentTo(render) splat.setPos(pos[0], pos[1], pos[2]) gagClass.hitSfx.play() Sequence(Wait(0.5), Func(splat.cleanup)).start() self.hitGag = None def d_makeSplat(self, index, pos): self.sendUpdate('makeSplat', [index, pos]) def b_makeSplat(self, index, pos): self.d_makeSplat(index, pos) self.makeSplat(index, pos) def handleGagCollision(self, entry, ent): x, y, z = ent.getGag().getPos(render) self.b_makeSplat(self.entities.index(ent), [x, y, z]) if self.isLocal(): intoNP = entry.getIntoNodePath() avNP = intoNP.getParent() for key in self.cr.doId2do.keys(): obj = self.cr.doId2do[key] if obj.__class__.__name__ == 'DistributedSuit': if obj.getKey() == avNP.getKey(): if obj.getHealth() > 0: obj.sendUpdate('hitByGag', [ent.getID()]) ent.cleanup() def setHealth(self, hp): DistributedAvatar.setHealth(self, hp) if self.isLocal(): base.localAvatar.getMyBattle().getTurretManager().updateTurretGui() def die(self): self.fsm.requestFinalState() turretPos = self.cannon.getPos(render) self.removeTurret() self.explosion = loader.loadModel("phase_3.5/models/props/explosion.bam") self.explosion.setScale(0.5) self.explosion.reparentTo(render) self.explosion.setBillboardPointEye() self.explosion.setPos(turretPos + (0, 0, 5)) sfx = base.audio3d.loadSfx("phase_3.5/audio/sfx/ENC_cogfall_apart.ogg") base.audio3d.attachSoundToObject(sfx, self) base.playSfx(sfx) messenger.send(self.deathEvent) def isLocal(self): return self.getOwner() == base.localAvatar.doId def getDeathEvent(self): return self.deathEvent
class QuietZoneState(StateData): def __init__(self, doneEvent, moveOn = 1): StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('quietZone', [State('off', self.enterOff, self.exitOff, ['waitForQuietZoneResponse']), State('waitForQuietZoneResponse', self.enterWaitForQuietZoneResponse, self.exitWaitForQuietZoneResponse, ['waitForSetZoneResponse']), State('waitForSetZoneResponse', self.enterWaitForSetZoneResponse, self.exitWaitForSetZoneResponse, ['waitForSetZoneComplete']), State('waitForSetZoneComplete', self.enterWaitForSetZoneComplete, self.exitWaitForSetZoneComplete, ['off'])], 'off', 'off') self.fsm.enterInitialState() self.moveOn = moveOn def getSetZoneCompleteEvent(self): return 'setZoneComplete-%s' % id(self) def getQuietZoneResponseEvent(self): return 'quietZoneResponse-%s' % id(self) def getEnterWaitForSetZoneResponseMsg(self): return 'enterWaitForSetZoneResponse-%s' % id(self) def unload(self): StateData.unload(self) del self.fsm def enter(self, requestStatus): StateData.enter(self) self._requestStatus = requestStatus base.localAvatar.b_setAnimState('off') self.fsm.request('waitForQuietZoneResponse') def exit(self): StateData.exit(self) if self._requestStatus.get('how', None) != 'doorOut': base.transitions.noTransitions() del self._requestStatus self.fsm.request('off') return def getDoneStatus(self): return self._requestStatus def enterOff(self): pass def exitOff(self): pass def handleWaitForQuietZoneResponse(self, msgType, di): if msgType == CLIENT_ENTER_OBJECT_REQUIRED: base.cr.handleQuietZoneGenerateWithRequired(di) elif msgType == CLIENT_ENTER_OBJECT_REQUIRED_OTHER: base.cr.handleQuietZoneGenerateWithRequiredOther(di) elif msgType == CLIENT_OBJECT_SET_FIELD: base.cr.handleQuietZoneUpdateField(di) else: base.cr.astronHandle(di) def enterWaitForQuietZoneResponse(self): self.setZoneDoneEvent = base.cr.getNextSetZoneDoneEvent() self.acceptOnce(self.setZoneDoneEvent, self._handleQuietZoneResponse) base.cr.sendQuietZoneRequest() def _handleQuietZoneResponse(self): if self.moveOn: self.fsm.request('waitForSetZoneResponse') else: messenger.send('enteredQuietZone') def exitWaitForQuietZoneResponse(self): self.ignore(self.setZoneDoneEvent) del self.setZoneDoneEvent def enterWaitForZoneRedirect(self): self.fsm.request('waitForSetZoneResponse') def exitWaitForZoneRedirect(self): pass def enterWaitForSetZoneResponse(self): zoneId = self._requestStatus['zoneId'] base.cr.sendSetZoneMsg(zoneId) self.fsm.request('waitForSetZoneComplete') def exitWaitForSetZoneResponse(self): pass def enterWaitForSetZoneComplete(self): self.setZoneDoneEvent = base.cr.getLastSetZoneDoneEvent() self.acceptOnce(self.setZoneDoneEvent, self._announceDone) def exitWaitForSetZoneComplete(self): self.ignore(self.setZoneDoneEvent) del self.setZoneDoneEvent def _announceDone(self): doneEvent = self.doneEvent requestStatus = self._requestStatus messenger.send(self.getSetZoneCompleteEvent(), [requestStatus]) messenger.send(doneEvent) def getRequestStatus(self): return self._requestStatus
class CogBrain(DirectObject): PANIC_SPEED = 0.15 PANIC_DELAY = 0.5 RUNAWAY_SPEED = 0.1 RUNAWAY_SAFE_DISTANCE = 50 MAX_BOSS_HELPERS = 5 PANIC_HP_FACTOR = 0.222 ATTACK_DISTANCE = 40.0 MAX_ATTACKERS = 3 Difficulty2MaxAttackThrows = {} for level in range(1, 5): Difficulty2MaxAttackThrows[level] = 3 for level in range(5, 10): Difficulty2MaxAttackThrows[level] = 4 for level in range(9, 13): Difficulty2MaxAttackThrows[level] = 5 def __init__(self, suit): self.suit = suit self.panicHP = self.suit.getMaxHealth() * self.PANIC_HP_FACTOR self.fsm = ClassicFSM('CogBrain', [State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('followBoss', self.enterFollowBoss, self.exitFollowBoss), State('panic', self.enterPanic, self.exitPanic), State('runAway', self.enterRunAway, self.exitRunAway)], 'off', 'off') self.fsm.enterInitialState() def start(self): taskMgr.add(self.__think, self.suit.uniqueName('think')) def end(self, andGoOff = 1): taskMgr.remove(self.suit.uniqueName('think')) if andGoOff: self.fsm.request('off') def __think(self, task = None): if task: task.delayTime = 1 if self.suit.getAttacking(): if task: return task.again else: return _help_priority = 0 _panic_priority = 0 _run_priority = 0 _helper_suits = 0 boss = None for av in self.suit.getManager().suits.values(): if av.doId != self.suit.doId: if av.head in ('vp',): boss = av for suit in self.suit.getManager().suits.values(): if suit.doId != self.suit.doId: if suit.brain: if suit.brain.fsm.getCurrentState().getName() == 'followBoss': _helper_suits += 1 if _helper_suits == self.MAX_BOSS_HELPERS - 1: _help_priority = 2 elif _helper_suits == self.MAX_BOSS_HELPERS - 2: _help_priority = 2.5 elif _helper_suits == self.MAX_BOSS_HELPERS - 3: _help_priority = 3.5 elif _helper_suits == self.MAX_BOSS_HELPERS - 4: _help_priority = 4 elif _helper_suits == self.MAX_BOSS_HELPERS - 5: _help_priority = 4.5 if boss == None or _helper_suits == self.MAX_BOSS_HELPERS: _help_priority = 0 if self.fsm.getCurrentState().getName() == 'followBoss': if self.bossSpotKey != boss.boss.spot: self.fsm.request('followBoss', [boss]) return task.again _toons_in_range = 0 in_range = 15 for av in self.suit.air.doId2do.values(): if av.__class__.__name__ == 'DistributedToonAI': if av.zoneId == self.suit.zoneId: if self.suit.getDistance(av) <= in_range: _toons_in_range += 1 if self.fsm.getCurrentState().getName() == 'followBoss': _panic_priority = _toons_in_range / 0.85 else: _panic_priority = _toons_in_range / 0.75 if self.fsm.getCurrentState().getName() == 'panic' and _toons_in_range > 0: _run_priority = 5 if self.suit.getHealth() <= self.panicHP: if _panic_priority < 4: _panic_priority = 4 if _run_priority == 5: self.fsm.request('runAway', [av]) del _help_priority del _panic_priority del _run_priority del _helper_suits del boss del in_range del _toons_in_range try: del av except: pass if task: return task.done else: return elif _panic_priority <= 2 and _help_priority <= 2: state_num = random.randint(0, 2) if state_num == 0 or state_num == 1: new_state = 'neutral' else: new_state = 'followBoss' if boss == None or _help_priority == 0: if self.fsm.getCurrentState().getName() != 'neutral': self.fsm.request('neutral') else: new_state = 'neutral' if self.fsm.getCurrentState().getName() != new_state: if self.fsm.getCurrentState().getName() == 'followBoss': del _help_priority del _panic_priority del _run_priority del _helper_suits del boss del in_range del _toons_in_range try: del args except: pass try: del new_state except: pass try: del state_num except: pass try: del av except: pass if task: return task.again else: return args = [] if new_state == 'followBoss': args = [boss] self.fsm.request(new_state, args) elif _panic_priority > _help_priority: if self.fsm.getCurrentState().getName() != 'panic': self.fsm.request('panic') del _help_priority del _panic_priority del _run_priority del _helper_suits del boss del in_range del _toons_in_range try: del args except: pass try: del new_state except: pass try: del state_num except: pass try: del av except: pass if task: return task.done else: return elif _panic_priority < _help_priority: if self.fsm.getCurrentState().getName() != 'followBoss': self.fsm.request('followBoss', [boss]) elif _panic_priority == _help_priority: new_state = random.choice(['panic', 'followBoss']) if self.fsm.getCurrentState().getName() != new_state: args = [] if new_state == 'followBoss': args = [boss] self.fsm.request(new_state, args) del _help_priority del _panic_priority del _run_priority del _helper_suits del boss del in_range del _toons_in_range try: del args except: pass try: del new_state except: pass try: del state_num except: pass try: del av except: pass if task: return task.again else: return def enterOff(self): pass def exitOff(self): pass def enterNeutral(self): self.suit.createPath(fromCurPos=True) self.numAttacksThrown = 0 if not self.suit.isBackup(): self.neutral_startLookingForToons() def neutral_startLookingForToons(self): taskMgr.add(self.__lookForToons, self.suit.uniqueName('lookForToon')) def neutral_stopLookingForToons(self): taskMgr.remove(self.suit.uniqueName('lookForToon')) def __lookForToons(self, task): if self.suit.isBackup() or not hasattr(self, 'numAttacksThrown'): return task.done elif self.suit.getAttacking(): task.delayTime = 1.0 return task.again elif self.numAttacksThrown >= self.Difficulty2MaxAttackThrows[self.suit.getLevel()]: self.numAttacksThrown = 0 if not self.suit.isWalking(): self.suit.createPath(path_key=self.suit.currentPath, fromCurPos=True) task.delayTime = 10 return task.again else: closestToonOrTurret = None obj2range = {} for obj in base.air.doId2do.values(): if obj.__class__.__name__ in ('DistributedToonAI', 'DistributedPieTurretAI'): if obj.zoneId == self.suit.zoneId: if not obj.isDead(): if obj.__class__.__name__ == 'DistributedToonAI': if obj.getNumAttackers() < self.MAX_ATTACKERS: dist = obj.getDistance(self.suit) if dist <= self.ATTACK_DISTANCE: obj2range[obj] = dist else: dist = obj.getDistance(self.suit) if dist <= self.ATTACK_DISTANCE: obj2range[obj] = dist ranges = [] for distance in obj2range.values(): ranges.append(distance) ranges.sort() for obj in obj2range.keys(): distance = obj2range[obj] if distance == ranges[0]: closestToonOrTurret = obj if closestToonOrTurret != None and not self.suit.getAttacking(): if self.suit.head != 'vp': if self.suit.walkTrack: self.ignore(self.suit.walkTrack.getName()) self.suit.walkTrack.clearToInitial() self.suit.walkTrack = None self.suit.b_setSuitState(3, -1, -1) self.suit.b_setAnimState('neutral') self.end(0) self.suit.headsUp(closestToonOrTurret) self.suit.attackToon(closestToonOrTurret) self.suit.setAttacking(True) if closestToonOrTurret.__class__.__name__ == 'DistributedToonAI': closestToonOrTurret.addNewAttacker(self.suit.doId) self.numAttacksThrown += 1 return task.done if self.numAttacksThrown > 0: if not self.suit.isWalking(): self.suit.createPath(path_key=self.suit.currentPath, fromCurPos=True) elif not self.suit.isWalking(): self.suit.createPath(fromCurPos=True) self.numAttacksThrown = 0 task.delayTime = 3.5 return task.again def exitNeutral(self): self.neutral_stopLookingForToons() del self.numAttacksThrown def enterPanic(self): taskMgr.add(self.__panic, self.suit.uniqueName('panic')) def __panic(self, task): self.suit.createPath(durationFactor=self.PANIC_SPEED, fromCurPos=True) if task.time == 2.0: self.__think(None) task.delayTime = self.PANIC_DELAY return task.again def exitPanic(self): taskMgr.remove(self.suit.uniqueName('panic')) def enterFollowBoss(self, boss): self.boss = boss if boss.boss.spot == None: self.bossSpot = boss.getPos(render) else: self.bossSpot = CIGlobals.SuitSpawnPoints[self.suit.hood][boss.boss.spot] if self.suit.currentPath == boss.boss.spot: self.suit.createPath(path_key=boss.boss.spot, fromCurPos=True) else: self.suit.currentPathQueue = SuitPathFinder.find_path(self.suit.hood, self.suit.currentPath, boss.boss.spot) self.suit.currentPathQueue.remove(self.suit.currentPathQueue[0]) self.suit.createPath(fromCurPos=True) taskMgr.add(self.__followBoss, self.suit.uniqueName('followBoss')) self.bossSpotKey = boss.boss.spot return def __followBoss(self, task): if self.boss not in self.suit.getManager().suits.values(): self.fsm.request('neutral') return task.done elif self.suit.getDistance(self.boss) <= 4: self.suit.b_setSuitState(3, -1, -1) if self.suit.walkTrack: self.suit.ignore(self.suit.walkTrack.getDoneEvent()) self.suit.walkTrack.pause() self.suit.walkTrack = None self.suit.b_setAnimState('neutral') self.suit.setH(self.suit.getH() - 180) self.suit.d_setH(self.suit.getH()) return task.done else: return task.cont def exitFollowBoss(self): self.suit.resetPathQueue() taskMgr.remove(self.suit.uniqueName('followBoss')) del self.boss del self.bossSpot del self.bossSpotKey def enterRunAway(self, toon): self.toon = toon self.suit.createPath(durationFactor=self.RUNAWAY_SPEED, fromCurPos=True) taskMgr.add(self.__runAway, self.suit.uniqueName('runAway')) def __runAway(self, task): try: if self.suit.getDistance(self.toon) >= self.RUNAWAY_SAFE_DISTANCE: self.start() return task.done if self.suit.walkTrack == None or self.suit.walkTrack.isStopped(): self.suit.createPath(durationFactor=self.RUNAWAY_SPEED, fromCurPos=True) return task.cont except: self.fsm.request('neutral') return task.done return def exitRunAway(self): taskMgr.remove(self.suit.uniqueName('runAway')) del self.toon
class MasterHuman(HumanBase.HumanBase, Biped.Biped): notify = DirectNotifyGlobal.directNotify.newCategory('Human') prebuiltAnimData = { } def __init__(self, other = None): Biped.Biped.__init__(self, other, HumanAnimationMixer) self.model = None self.useFaceTex = True self.joints = { } self.jointTrans = { } self.jointTrans2 = { } self.zombie = False self.crazyColorSkin = False self.crazyColorSkinIndex = 0 self.flattenPending = None self.optimizeLOD = base.config.GetBool('optimize-avatar-lod', 1) self.master = 0 self.loaded = 0 self.playingRate = None self.shadowFileName = 'models/misc/drop_shadow' self.setFont(PiratesGlobals.getInterfaceFont()) self._MasterHuman__blinkName = 'blink-' + str(self.this) self.eyeLids = None self.eyeBalls = None self.eyeIris = None self.reducedAnimList = None self.rootScale = 1.0 self.headNode = None self.extraNode = None self.scaleNode = None self.rootNode = None self.floorOffsetZ = 0.0 self.headFudgeHpr = Vec3(0, 0, 0) self.frozeSomething = True self.randGen = random.Random() self.randGen.seed(random.random()) self.eyeFSM = ClassicFSM('eyeFSM', [ State('off', self.enterEyeFSMOff, self.exitEyeFSMOff, [ 'open', 'closed']), State('open', self.enterEyeFSMOpen, self.exitEyeFSMOpen, [ 'closed', 'off']), State('closed', self.enterEyeFSMClosed, self.exitEyeFSMClosed, [ 'open', 'off'])], 'off', 'off') self.eyeFSM.enterInitialState() if other != None: self.copyHuman(other) self.isPaid = False def removeCopiedNodes(self): self.dropShadow = self.find('**/drop_shadow*') if not self.dropShadow.isEmpty(): self.deleteDropShadow() else: self.dropShadow = None def flattenHuman(self): self.deleteNametag3d() self.getWeaponJoints() def _MasterHuman__doneFlattenHuman(self, models): self.flattenPending = None self.getWeaponJoints() def copyHuman(self, other): self.gender = other.gender self.loaded = other.loaded self.type = other.type self.loadAnimatedHead = other.loadAnimatedHead self.model = None def delete(self): try: pass except: self.Human_deleted = 1 taskMgr.remove(self._MasterHuman__blinkName) if self.dropShadow and not self.dropShadow.isEmpty(): self.deleteDropShadow() del self.eyeFSM self.controlShapes = None self.sliderNames = None if self.model: self.model.delete() del self.model Biped.Biped.delete(self) def isDeleted(self): try: if self.Human_deleted == 1: return True except: return False def fixEyes(self): self.eyeLids = { } self.eyeBalls = { } self.eyeIris = { } for lodName in self.getLODNames(): geom = self.getPart('head', lodName) self.eyeLids[lodName] = geom.findAllMatches('**/*eyelid*') self.eyeBalls[lodName] = geom.findAllMatches('**/eye_ball*') self.eyeIris[lodName] = geom.findAllMatches('**/eye_iris*') self.eyeLids[lodName].stash() self.eyeBalls[lodName].unstash() self.eyeIris[lodName].unstash() def getCrazyColorSkinIndex(self): return self.crazyColorSkinIndex def setCrazyColorSkinIndex(self, index): if len(HumanDNA.crazySkinColors) > index: self.crazyColorSkinIndex = index else: self.notify.warning('(MasterHuman)index: %d is out of bounds for crazyColorSkin: %d' % (index, len(HumanDNA.crazySkinColors))) def generateSkinColor(self): skinColor = self.style.getSkinColor() lowColor = self.model.lowLODSkinColor color = VBase4(lowColor[0] * skinColor[0], lowColor[1] * skinColor[1], lowColor[2] * skinColor[2], 1.0) self.model.faces[0].setColorScale(skinColor) if self.model.newAvatars: self.model.currentBody.setColorScale(skinColor) if self.optimizeLOD: self.model.currentBody[2].setColorScale(color) self.model.faces[0][2].setColorScale(color) else: numPaths = self.model.body.getNumPaths() medIdx = numPaths / 3 lowIdx = (numPaths / 3) * 2 if self.zombie: self.model.body.setColorScale(Vec4(1, 1, 1, 1)) if self.optimizeLOD: color = VBase4(121 / 255.0, 124 / 255.0, 103 / 255.0, 1.0) for i in xrange(lowIdx, numPaths): self.model.body[i].setColorScale(color) self.model.faceZomb[2].setColorScale(color) else: self.model.body.setColorScale(skinColor) lowColor = self.model.lowLODSkinColor if self.optimizeLOD: color = VBase4(lowColor[0] * skinColor[0], lowColor[1] * skinColor[1], lowColor[2] * skinColor[2], 1.0) for i in xrange(lowIdx, numPaths): self.model.body[i].setColorScale(color) def generateSkinTexture(self): bodyTextureIdx = self.style.body.skin if self.zombie: if self.gender == 'f': bodyTextureIdx = PirateFemale.ZOMB_BODY_TEXTURE else: bodyTextureIdx = PirateMale.ZOMB_BODY_TEXTURE if self.gender == 'f': body_textures = PirateFemale.body_textures[self.style.body.shape] else: body_textures = PirateMale.body_textures[0] #self.style.body.shape] tex_name = self.getTrySafe(body_textures, bodyTextureIdx) if tex_name != None: tex = self.model.bodyTextures.findTexture(tex_name) else: return None if tex: for parts in self.model.bodys: numPaths = parts.getNumPaths() for i in xrange(numPaths): parts[i].setTexture(tex, 1) def generateFaceTexture(self, default): if default: faceTextureIdx = 0 else: faceTextureIdx = self.style.head.texture if faceTextureIdx >= len(self.model.faceTexturesSet): faceTextureIdx = 0 self.model.faces[0].setTexture(self.model.faceTexturesSet[faceTextureIdx]) def generateHairColor(self, colorName = None, colorModel = None): self.model.setHairBaseColor() def getTrySafe(self, list, idx): try: if type(idx) == str: lookup = idx.split('_cut')[0] else: lookup = idx return list[lookup] except: return None def generateEyesTexture(self): eyesTextureIdx = self.style.head.eyes.color if self.gender == 'f': eye_iris_textures = PirateFemale.eye_iris_textures else: eye_iris_textures = PirateMale.eye_iris_textures tex_name = self.getTrySafe(eye_iris_textures, eyesTextureIdx) if tex_name != None: tex = self.eyeIrisTextures.findTexture(tex_name) else: return None if tex: self.model.irises.setTexture(tex, 1) def generateHatColor(self): style = self.model.dna if self.zombie: style = self.model.dnaZomb hatColor = style.lookupHatColor() geom = self.getGeomNode() parts = geom.findAllMatches('**/hat_band*') parts.setColorScale(hatColor) def generateClothesColor(self): style = self.model.dna if self.zombie: style = self.model.dnaZomb clothesTopColor = style.lookupClothesTopColor() clothesBotColor = style.lookupClothesBotColor() geom = self.getGeomNode() if self.optimizeLOD: def tempColorParts(parts, ct): numPaths = parts.getNumPaths() lowIdx = (numPaths / 3) * 2 for j in xrange(lowIdx): parts[j].setColorScale(ct) for j in xrange(lowIdx, numPaths): cl = parts[j].getColorScale() compoundColor = VBase4(cl[0] * ct[0], cl[1] * ct[1], cl[2] * ct[2], 1.0) parts[j].setColorScale(compoundColor) else: def tempColorParts(parts, ct): parts.setColorScale(ct) colorParts = tempColorParts parts = geom.findAllMatches('**/clothing_layer1_shirt*') colorParts(parts, clothesTopColor[0]) parts = geom.findAllMatches('**/clothing_layer2_vest*') colorParts(parts, clothesTopColor[1]) parts = geom.findAllMatches('**/clothing_layer3_coat*') colorParts(parts, clothesTopColor[2]) parts = geom.findAllMatches('**/clothing_layer1_pant*') colorParts(parts, clothesBotColor[0]) del colorParts def generateTexture(self): self.generateFaceTexture(not (self.useFaceTex)) self.generateEyesTexture() def generateColor(self): self.generateSkinColor() self.generateHairColor() self.generateHatColor() def makeAnimDict(self, gender, animNames): self.animTable = [] for currAnim in animNames: anim = animNames.get(currAnim) for currAnimName in anim: self.animTable.append([ currAnimName, currAnimName]) self.reducedAnimList = self.animTable def forceLoadAnimDict(self): for anim in self.animTable: self.getAnimControls(anim[0]) def createAnimDict(self, customList = None): if self.reducedAnimList is None: self.animDict = self.prebuiltAnimData[self.gender + self.type] return None if self.gender == 'f': filePrefix = 'models/char/f' genderPrefix = 'f' else: filePrefix = 'models/char/m' genderPrefix = 'm' filePrefix += 'p' animList = self.reducedAnimList if animList is None: animList = AnimListDict[self.type] self.animDict = { } for anim in animList: animSuffix = '' for i in range(0, len(CustomAnimDict[genderPrefix + self.type])): if anim[0] == CustomAnimDict[genderPrefix + self.type][i]: animSuffix = '_' + genderPrefix + NewModelDict.get(self.type) break continue self.animDict[anim[0]] = filePrefix + '_' + anim[1] + animSuffix if self.reducedAnimList is None: self.animDict.pop('intro') return filePrefix def generateBody(self, copy = 1): if self.gender == 'm': filePrefix = 'models/char/mp' else: filePrefix = 'models/char/fp' messenger.send('tick') lodString = '2000' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '2000', copy) messenger.send('tick') if loader.loadModel(filePrefix + '_' + '1000', allowInstance = True) != None: lodString = '1000' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '1000', copy) messenger.send('tick') if loader.loadModel(filePrefix + '_' + '500', allowInstance = True) != None: lodString = '500' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '500', copy) messenger.send('tick') self.makeSubpart('head', [ 'zz_head01'], []) self.makeSubpart('torso', [ 'zz_spine01'], [ 'zz_head01']) self.makeSubpart('legs', [ 'dx_root'], [ 'zz_spine01']) self.setSubpartsComplete(True) self.eyeIrisTextures = loader.loadModel('models/misc/eye_iris.bam') def setLODs(self): self.setLODNode() avatarDetail = base.config.GetString('avatar-detail', 'high') if avatarDetail == 'high': dist = [ 0, 20, 80, 1000000000] elif avatarDetail == 'med': dist = [ 0, 10, 20, 1000000000] elif avatarDetail == 'low': dist = [ 0, 0, 10, 1000000000] else: raise StandardError, 'Invalid avatar-detail: %s' % avatarDetail self.addLOD(2000, dist[1], dist[0]) self.addLOD(1000, dist[2], dist[1]) self.addLOD(500, dist[3], dist[2]) if self.optimizeLOD: lowLOD = self.getLOD('500') lowLOD.setTransparency(0, 1000) self.getLODNode().setCenter(Point3(0, 0, 5)) def showLOD(self, lodName): self.generateTexture() self.model.setFromDNA() tex = self.model.faces[0][2].findTexture('*face*') def loadHuman(self, gender = 'm', other = None): self.gender = gender if self.gender == 'f': controlShapes = PirateFemale.ControlShapes sliderNames = PirateFemale.SliderNames else: controlShapes = PirateMale.ControlShapes sliderNames = PirateMale.SliderNames self.setLODs() self.loadAnimatedHead = True self.generateBody() if self.gender == 'f': self.type = BodyDefs.femaleFrames[self.style.getBodyShape()] self.model = PirateFemale.PirateFemale(self, self.style) else: self.type = BodyDefs.maleFrames[self.style.getBodyShape()] self.model = PirateMale.PirateMale(self, self.style) self.faceAwayFromViewer() self.lods = self.getLODNames() if self.gender == 'f': self.headFudgeHpr = Vec3(0, 0, 0) idx = 1 else: self.headFudgeHpr = Vec3(0, 0, 0) idx = 0 messenger.send('tick') self.model.setupHead(2000) messenger.send('tick') self.model.setupBody(2000) messenger.send('tick') self.model.setupClothing(2000) messenger.send('tick') if self.master: self.model.setupSelectionChoices('NPC') self.showNormal() self.createAnimDict() messenger.send('tick') self.initAnimsOnAllLODs([ 'head', 'legs', 'torso', 'modelRoot']) messenger.send('tick') self.controlShapes = controlShapes self.sliderNames = sliderNames self.initHeadControlShapes() self.storeJoints() self.find('**/nametag3d').detachNode() self.findAllMatches('**/name_tag').detach() self.rootNode = self.getLOD('2000').find('**/dx_root') self.floorOffsetZ = self.rootNode.getZ() messenger.send('tick') root = self.getLOD('500') gr = SceneGraphReducer() gr.applyAttribs(root.node(), gr.TTTransform | gr.TTTexMatrix | gr.TTOther) gr.makeCompatibleFormat(root.node(), 0) gr.premunge(root.node(), RenderState.makeEmpty()) gr.decompose(root.node()) stashedSet = root.findAllMatches('**/@@*') stashedSet.unstash() gr.makeCompatibleFormat(root.node(), 0) stashedSet.stash() messenger.send('tick') for face in self.model.faces[0]: node = face.node() for i in range(node.getNumGeoms()): face.node().setGeomState(i, RenderState.makeEmpty()) def initializeMiscNodes(self): self.initializeNametag3d() self.initializeDropShadow() if self.getLOD('2000') == None: return None exposedHeadJoint = self.getLOD('2000').find('**/def_head01') if not exposedHeadJoint.isEmpty(): idx = 0 if self.gender == 'f': idx = 1 exposedHeadJoint.setScale(1) self.headNode.reparentTo(exposedHeadJoint) self.headNode.setScale(HeadScales[idx][self.style.getBodyShape()]) def undoControlJoints(self): self.getGeomNode().getParent().findAllMatches('def_*').detach() self.getGeomNode().getParent().findAllMatches('trs_*').detach() self.findAllMatches('def_*').detach() self.findAllMatches('trs_*').detach() def cleanupHuman(self, gender = 'm'): self.eyeFSM.request('off') self.undoControlJoints() self.eyeLids = { } self.eyeBalls = { } self.eyeIris = { } self.flush() self.loaded = 0 self.master = 0 def generateHuman(self, gender = 'm'): self.loadHuman(self.style.gender) def getShadowJoint(self): return self def getNametagJoints(self): joints = [] for lodName in self.getLODNames(): bundle = self.getPartBundle('legs', lodName) joint = bundle.findChild('name_tag') if joint: joints.append(joint) continue return joints def _MasterHuman__blinkOpenEyes(self, task): if self.eyeFSM.getCurrentState().getName() == 'closed': self.eyeFSM.request('open') r = self.randGen.random() if r < 0.10000000000000001: t = 0.20000000000000001 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self._MasterHuman__blinkCloseEyes, self._MasterHuman__blinkName) return Task.done def _MasterHuman__blinkCloseEyes(self, task): if self.eyeFSM.getCurrentState().getName() != 'open': taskMgr.doMethodLater(4.0, self._MasterHuman__blinkCloseEyes, self._MasterHuman__blinkName) else: self.eyeFSM.request('closed') taskMgr.doMethodLater(0.125, self._MasterHuman__blinkOpenEyes, self._MasterHuman__blinkName) return Task.done def startBlink(self): taskMgr.remove(self._MasterHuman__blinkName) if self.eyeLids: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self._MasterHuman__blinkCloseEyes, self._MasterHuman__blinkName) def stopBlink(self): taskMgr.remove(self._MasterHuman__blinkName) if self.eyeLids: self.eyeFSM.request('open') def closeEyes(self): self.eyeFSM.request('closed') def openEyes(self): self.eyeFSM.request('open') def enterEyeFSMOff(self): pass def exitEyeFSMOff(self): pass def enterEyeFSMOpen(self): for lodName in self.getLODNames(): if not self.eyeLids[lodName].isEmpty(): self.eyeLids[lodName].hide() self.eyeBalls[lodName].show() self.eyeIris[lodName].show() continue def exitEyeFSMOpen(self): pass def enterEyeFSMClosed(self): return None for lodName in self.getLODNames(): if not self.eyeLids[lodName].isEmpty(): self.eyeLids[lodName].show() self.eyeBalls[lodName].hide() self.eyeIris[lodName].hide() continue def exitEyeFSMClosed(self): pass def setControlValue(self, r, name): if self.style.getGender() == 'f': matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix else: matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix shapes = self.controlShapes ctl = shapes[name] slider = ctl[0] if r < 0.0: if len(ctl) > 1: slider = ctl[1] for i in range(0, len(slider)): jointName = slider[i][0] jointCtls = self.findAllMatches(jointName) posI = matrixI[jointName][0] hprI = matrixI[jointName][1] sclI = matrixI[jointName][2] posF = VBase3(posI[0], posI[1], posI[2]) hprF = VBase3(hprI[0], hprI[1], hprI[2]) sclF = VBase3(sclI[0], sclI[1], sclI[2]) self.notify.debug('scv: %s initial %s' % (jointName, posI)) dr = slider[i][4] * r ctl[0][i][5] = dr posDelta = VBase3(0, 0, 0) hprDelta = VBase3(0, 0, 0) sclDelta = VBase3(0, 0, 0) for sliderIdx in xrange(0, len(matrixF[jointName])): sliderName = matrixF[jointName][sliderIdx] jointSet = shapes[sliderName][0] for jointIdx in xrange(0, len(jointSet)): if jointSet[jointIdx][0] == jointName: if jointSet[jointIdx][1] == TX: posDelta.setX(posDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == TY: posDelta.setY(posDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == TZ: posDelta.setZ(posDelta.getZ() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RX: hprDelta.setX(hprDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RY: hprDelta.setY(hprDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RZ: hprDelta.setZ(hprDelta.getZ() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SX: if r < 0.0: sclDelta.setX(sclDelta.getX() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setX(sclDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SY: if r < 0.0: sclDelta.setY(sclDelta.getY() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setY(sclDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SZ: if r < 0.0: sclDelta.setZ(sclDelta.getZ() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setZ(sclDelta.getZ() + jointSet[jointIdx][5]) else: self.notify.warning('scv:wrong element = %s' % jointSet[jointIdx][1]) jointSet[jointIdx][1] == TX self.notify.debug('scv: %s composite posDelta = %s' % (jointName, posDelta)) posF.setX(posI[0] + posDelta[0]) posF.setY(posI[1] + posDelta[1]) posF.setZ(posI[2] + posDelta[2]) self.notify.debug('scv: %s final posDelta%s' % (jointName, posF)) self.notify.debug('scv: %s composite hprDelta = %s' % (jointName, hprDelta)) hprF.setX(hprI[0] + hprDelta[0]) hprF.setY(hprI[1] + hprDelta[1]) hprF.setZ(hprI[2] + hprDelta[2]) self.notify.debug('scv: %s final hprDelta%s' % (jointName, hprF)) self.notify.debug('scv: %s composite sclDelta = %s' % (jointName, sclDelta)) sclF.setX(sclI[0] + sclDelta[0]) sclF.setY(sclI[1] + sclDelta[1]) sclF.setZ(sclI[2] + sclDelta[2]) self.notify.debug('scv: %s final sclDelta%s' % (jointName, sclF)) for j in range(0, jointCtls.getNumPaths()): jointCtl = jointCtls[j] jointCtl.setPosHprScale(posF, hprF, sclF) def applyBodyShaper(self): if self.style.getGender() == 'f': tjs = FemaleBodyShapeTranslateJoints sjs = FemaleBodyShapeScaleJoints matrix = FemaleBodyShapeControlJointMatrix else: tjs = MaleBodyShapeTranslateJoints sjs = MaleBodyShapeScaleJoints matrix = MaleBodyShapeControlJointMatrix type = 0 #self.style.getBodyShape() for jointName in tjs: transData = self.jointTrans[jointName] vector = matrix[jointName][type] self.joints[jointName].applyFreezeMatrix(vector, transData[1], transData[2]) for jointName in sjs: transData = self.jointTrans[jointName] vector = matrix[jointName][type] self.joints[jointName].applyFreezeMatrix(transData[0], transData[1], vector) value = self.style.getHeadSize() mappedValue = 0.90000000000000002 + (1 + value) * 0.10000000000000001 transData = self.jointTrans['def_extra_jt'] self.joints['def_extra_jt'].applyFreezeMatrix(transData[0], transData[1], Vec3(2 - mappedValue, mappedValue, 1)) transData = self.jointTrans['def_head01'] idx = 0 if self.style.gender == 'f': idx = 1 self.joints['def_head01'].applyFreezeMatrix(transData[0], transData[1], Vec3(HeadScales[idx][0])) #self.style.getBodyShape()])) self.setGlobalScale(self.calcBodyScale()) def undoBodyShaper(self): if self.style.getGender() == 'f': cjs = FemaleBodyShapeControlJoints else: cjs = MaleBodyShapeControlJoints def applyHeadShaper(self): self.setHeadControlShapeValues() def undoHeadShaper(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints else: cjs = MaleHeadShapeControlJoints def createControlJoints(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints else: cjs = MaleHeadShapeControlJoints for jointName in cjs: for lodName in self.getLODNames(): if lodName == '2000': joint = self.controlJoint(None, 'legs', jointName, lodName) continue if lodName == '1000': continue continue if lodName == '500': continue continue def initHeadControlShapes(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix matrixIHelper = FemaleHeadInitHelper else: cjs = MaleHeadShapeControlJoints matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix matrixIHelper = MaleHeadInitHelper if len(matrixF['initialized']) > 0: return None initializedMatrixI = len(matrixI['initialized']) initializedMatrixF = len(matrixF['initialized']) for jointName in cjs: transform = TransformState.makeMat(self.getJointTransform('legs', jointName, '2000')) pos = Vec3(transform.getPos()) hpr = Vec3(transform.getHpr()) scale = Vec3(transform.getScale()) matrixI[jointName].append(pos) matrixI[jointName].append(hpr) matrixI[jointName].append(scale) matrixIHelper[jointName] = [ pos[0], pos[1], pos[2], hpr[0], hpr[1], hpr[2], scale[0], scale[1], scale[2]] matrixI['initialized'].append('initialized') shapes = self.controlShapes names = self.sliderNames for i in xrange(0, len(shapes)): slider = shapes[names[i]] for k in xrange(0, len(slider[0])): slider[0][k][4] = slider[0][k][2] if len(slider) > 1: slider[1][k][4] = slider[1][k][2] continue for i in xrange(0, len(shapes)): slider = shapes[names[i]] for k in xrange(0, len(slider[0])): jointCtl = slider[0][k] jointName = jointCtl[0] matrixF[jointName].append(names[i]) pos = matrixI[jointName][0] hpr = matrixI[jointName][1] scl = matrixI[jointName][2] if jointCtl[1] < 3: posDelta = jointCtl[4] - pos[jointCtl[1]] jointCtl[4] = posDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = posDelta len(slider) > 1 if jointCtl[1] > 2 and jointCtl[1] < 6: hprDelta = jointCtl[4] - hpr[jointCtl[1] - 3] jointCtl[4] = hprDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = hprDelta len(slider) > 1 sclDelta = 12 #jointCtl[4] - scl[jointCtl[1] - 6] jointCtl[4] = sclDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = sclDelta continue matrixF['initialized'].append('initialized') def setHeadControlShapeValues_old(self): value = self.style.getHeadSize() mappedValue = 0.90000000000000002 + (1 + value) * 0.10000000000000001 self.setControlValue(self.style.getHeadWidth(), 'headWidth') self.setControlValue(self.style.getHeadHeight(), 'headHeight') self.setControlValue(self.style.getHeadRoundness(), 'headRoundness') self.setControlValue(self.style.getJawWidth(), 'jawWidth') self.setControlValue(self.style.getJawAngle(), 'jawChinAngle') self.setControlValue(self.style.getJawChinSize(), 'jawChinSize') self.setControlValue(self.style.getJawLength(), 'jawLength') self.setControlValue(self.style.getMouthWidth(), 'mouthWidth') self.setControlValue(self.style.getMouthLipThickness(), 'mouthLipThickness') self.setControlValue(self.style.getCheekFat(), 'cheekFat') self.setControlValue(self.style.getBrowProtruding(), 'browProtruding') self.setControlValue(self.style.getEyeCorner(), 'eyeCorner') self.setControlValue(self.style.getEyeOpeningSize(), 'eyeOpeningSize') self.setControlValue(self.style.getEyeBulge(), 'eyeSpacing') self.setControlValue(self.style.getNoseBridgeWidth(), 'noseBridgeWidth') self.setControlValue(self.style.getNoseNostrilWidth(), 'noseNostrilWidth') self.setControlValue(self.style.getNoseLength(), 'noseLength') self.setControlValue(self.style.getNoseBump(), 'noseBump') self.setControlValue(self.style.getNoseNostrilHeight(), 'noseNostrilHeight') self.setControlValue(self.style.getNoseNostrilAngle(), 'noseNostrilAngle') self.setControlValue(self.style.getNoseBridgeBroke(), 'noseBridgeBroke') self.setControlValue(self.style.getNoseNostrilBroke(), 'noseNostrilBroke') self.setControlValue(self.style.getEarScale(), 'earScale') self.setControlValue(self.style.getEarFlapAngle(), 'earFlap') self.setControlValue(self.style.getEarPosition(), 'earPosition') def getGlobalScale(self): return self.scaleNode.getScale() def setGlobalScale(self, scale): transData = self.jointTrans['def_head01'] pos = Vec3(transData[0]) pos.setZ(-(self.floorOffsetZ * (1 - scale))) self.joints['def_scale_jt'].applyFreezeMatrix(pos, transData[1], Vec3(scale)) self.rootScale = scale def calcBodyScale(self): idx = 0 if self.gender == 'f': idx = 1 mappedValue = (0.80000000000000004 + (1 + self.style.getBodyHeight()) * 0.20000000000000001) * BodyScales[idx][0]#self.style.getBodyShape()] return mappedValue def showZombie(self): self.model.irises.stash() self.model.faces[0].stash() self.model.faceZomb.unstash() self.generateSkinTexture() def showNormal(self): self.model.irises.unstash() self.model.faces[0].unstash() self.model.faceZomb.stash() self.generateSkinTexture() def takeAwayTexture(self, geoms, omitFace = False): emptyRenderState = RenderState.makeEmpty() eyeIrisColor = VBase4(0, 0, 0, 1) for i in range(0, geoms.getNumPaths()): element = geoms[i] if 'eye_iris' in element.getName(): element.setColorScale(eyeIrisColor) elif omitFace and 'master_face' in element.getName(): continue element.setTextureOff() geom = element.node() for j in range(0, geom.getNumGeoms()): geom.setGeomState(j, emptyRenderState) def optimizeMedLOD(self): medLOD = self.getLOD('1000') geoms = medLOD.findAllMatches('**/teeth*') geoms.stash() self.medSkinGone = False geoms = medLOD.find('**/body_forearm*') if geoms.isEmpty(): self.medSkinGone = True geoms = medLOD.findAllMatches('**/body_*') self.takeAwayTexture(geoms, True) geoms = medLOD.findAllMatches('**/hair_*') self.takeAwayTexture(geoms) if self.gender != 'f': geoms = medLOD.findAllMatches('**/beard_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/mustache_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/eye_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/clothing_layer2_belt_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/clothing_layer1_shoe_*') self.takeAwayTexture(geoms) def optimizeLowLOD(self): lowLOD = self.getLOD('500') geoms = lowLOD.findAllMatches('**/teeth*') geoms.stash() geoms = lowLOD.findAllMatches('**/+GeomNode') self.takeAwayTexture(geoms) def setHeadControlShapeValues(self): value = self.style.getHeadSize() mappedValue = 0.90000000000000002 + (1 + value) * 0.10000000000000001 self.setControlValue_new(self.style.getHeadWidth(), 'headWidth') self.setControlValue_new(self.style.getHeadHeight(), 'headHeight') self.setControlValue_new(self.style.getHeadRoundness(), 'headRoundness') self.setControlValue_new(self.style.getJawWidth(), 'jawWidth') self.setControlValue_new(self.style.getJawAngle(), 'jawChinAngle') self.setControlValue_new(self.style.getJawChinSize(), 'jawChinSize') self.setControlValue_new(self.style.getJawLength(), 'jawLength') self.setControlValue_new(self.style.getMouthWidth(), 'mouthWidth') self.setControlValue_new(self.style.getMouthLipThickness(), 'mouthLipThickness') self.setControlValue_new(self.style.getCheekFat(), 'cheekFat') self.setControlValue_new(self.style.getBrowProtruding(), 'browProtruding') self.setControlValue_new(self.style.getEyeCorner(), 'eyeCorner') self.setControlValue_new(self.style.getEyeOpeningSize(), 'eyeOpeningSize') self.setControlValue_new(self.style.getEyeBulge(), 'eyeSpacing') self.setControlValue_new(self.style.getNoseBridgeWidth(), 'noseBridgeWidth') self.setControlValue_new(self.style.getNoseNostrilWidth(), 'noseNostrilWidth') self.setControlValue_new(self.style.getNoseLength(), 'noseLength') self.setControlValue_new(self.style.getNoseBump(), 'noseBump') self.setControlValue_new(self.style.getNoseNostrilHeight(), 'noseNostrilHeight') self.setControlValue_new(self.style.getNoseNostrilAngle(), 'noseNostrilAngle') self.setControlValue_new(self.style.getNoseBridgeBroke(), 'noseBridgeBroke') self.setControlValue_new(self.style.getNoseNostrilBroke(), 'noseNostrilBroke') self.setControlValue_new(self.style.getEarScale(), 'earScale') self.setControlValue_new(self.style.getEarFlapAngle(), 'earFlap') self.setControlValue_new(self.style.getEarPosition(), 'earPosition') self.postProcess_setHeadControlShapeValues() def setControlValue_new(self, r, name): ctl = self.controlShapes[name] zeroindex = ctl[0] sliders = zeroindex if r < 0.0: if len(ctl) > 1: sliders = ctl[1] for i in range(0, len(sliders)): zeroindex[i][5] = sliders[i][4] * r def postProcess_setHeadControlShapeValues(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints matrixF = FemaleHeadShapeControlJointMatrix matrixIHelper = FemaleHeadInitHelper else: cjs = MaleHeadShapeControlJoints matrixF = MaleHeadShapeControlJointMatrix matrixIHelper = MaleHeadInitHelper for jointName in cjs: transList = list(matrixIHelper[jointName]) for sliderName in matrixF[jointName]: for sliderJoint in self.controlShapes[sliderName][0]: if sliderJoint[0] == jointName: transList[sliderJoint[1]] += sliderJoint[5] continue self.joints[jointName].applyFreezeMatrix(Vec3(*transList[0:3]), Vec3(*transList[3:6]), Vec3(*transList[6:9])) def quickGetJointTransform(self, jointName): return self.joints[jointName][0].getDefaultValue() def storeJoints(self): if self.style.gender == 'm': bJoints = MaleBodyShapeControlJoints hJoints = MaleHeadShapeControlJoints else: bJoints = FemaleBodyShapeControlJoints hJoints = FemaleHeadShapeControlJoints for name in bJoints + hJoints + ('def_head01', 'def_extra_jt', 'def_scale_jt'): joint = self.getJoints(jointName = name) self.joints[name] = joint[0] ts = TransformState.makeMat(joint[0].getDefaultValue()) self.jointTrans[name] = (Vec3(ts.getPos()), Vec3(ts.getHpr()), Vec3(ts.getScale())) def setupAnimDicts(cls): for t in BodyDefs.maleFrames: cls.storeAnimDict('models/char/mp', 'm', t) for t in BodyDefs.femaleFrames: cls.storeAnimDict('models/char/fp', 'f', t) setupAnimDicts = classmethod(setupAnimDicts) def storeAnimDict(cls, prefix, gender, type): qualifier = gender + type animList = AnimListDict[type] cls.prebuiltAnimData[qualifier] = { } for anim in animList: animSuffix = '' for i in range(0, len(CustomAnimDict[qualifier])): if anim[0] == CustomAnimDict[qualifier][i]: animSuffix = '_' + gender + NewModelDict.get(type) break continue cls.prebuiltAnimData[qualifier][anim[0]] = prefix + '_' + anim[1] + animSuffix cls.prebuiltAnimData[qualifier].pop('intro') storeAnimDict = classmethod(storeAnimDict)
class DistributedEagleGame(DistributedMinigame): notify = directNotify.newCategory('DistributedEagleGame') Round2MusicSpeed = {1: 1.0, 2: 1.15, 3: 1.35} def __init__(self, cr): DistributedMinigame.__init__(self, cr) self.platformPositions = {0: (-5, 0.5, -0.5), 1: (-15, 0.5, -0.5), 2: (5, 0.5, -0.5), 3: (15, 0.5, -0.5)} self.fsm.addState(State('roundCountdown', self.enterRoundCountdown, self.exitRoundCountdown, ['play'])) self.fsm.addState(State('roundOver', self.enterRoundOver, self.exitRoundOver, ['finalScores', 'roundCountdown'])) self.fsm.addState(State('finalScores', self.enterFinalScores, self.exitFinalScores, ['gameOver'])) self.fsm.getStateNamed('waitForOthers').addTransition('roundCountdown') self.fsm.getStateNamed('play').addTransition('roundOver') self.fsm.getStateNamed('gameOver').addTransition('finalScores') self.cannonFSM = ClassicFSM('Cannon', [State('off', self.enterOff, self.exitOff), State('control', self.enterControlCannon, self.exitControlCannon), State('fly', self.enterFly, self.exitFly)], 'off', 'off') self.cannonFSM.enterInitialState() self.hitEagleSfx = None self.toonOof = None self.cannonMoveSfx = None self.fallSfx = None self.bgColor = (0.05, 0.05, 0.05) self.cannonId = None self.cannonBarrel = '**/cannon' self.fog = None self.platforms = [] self.round = 0 self.world = None self.worldModelPath = 'phase_5/models/cogdominium/tt_m_ara_cfg_quadrant2.bam' self.nodesToStash = ['lights', 'streamers', 'tt_m_ara_cfg_girders2b:Rwall_col', 'tt_m_ara_cfg_girders2b:Lwall_col'] self.triggers = ['tt_m_ara_cfg_clump2:col_clump2', 'tt_m_ara_cfg_clump4:col_clump4', 'tt_m_ara_cfg_clump5:col_clump5', 'tt_m_ara_cfg_clump6:col_clump6', 'tt_m_ara_cfg_clump7:col_clump7', 'tt_m_ara_cfg_base:ceiling_collision'] return def allRoundsEnded(self): self.fsm.request('finalScores') def roundOver(self): if self.cannonId == None: self.__handleMissedEagle() self.fsm.request('roundOver') return def enterControlCannon(self): self.__setupCamera(1) self.cannon = self.cr.doId2do.get(self.cannonId) array = [] array.append(inputState.watchWithModifiers('cannonUp', 'arrow_up', inputSource=inputState.ArrowKeys)) array.append(inputState.watchWithModifiers('cannonDown', 'arrow_down', inputSource=inputState.ArrowKeys)) array.append(inputState.watchWithModifiers('cannonLeft', 'arrow_left', inputSource=inputState.ArrowKeys)) array.append(inputState.watchWithModifiers('cannonRight', 'arrow_right', inputSource=inputState.ArrowKeys)) self.cist = array taskMgr.add(self.__handleCannonControls, 'DEagleGame-handleCannonControls') taskMgr.add(self.__broadcastCannonAndLTTask, 'DEagleGame-broadcastCannonAndLT') self.acceptOnce('control', self.controlKeyPressed) def broadcastLTPos(self): lt = base.localAvatar lt.d_setPosHpr(lt.getX(render), lt.getY(render), lt.getZ(render), lt.getH(render), lt.getP(render), lt.getR(render)) def __broadcastCannonAndLTTask(self, task): self.cannon.d_setBarrelOrientation(self.cannon.find(self.cannonBarrel).getH(), self.cannon.find(self.cannonBarrel).getP()) self.broadcastLTPos() task.delayTime = 0.5 return task.again def __handleCannonControls(self, task): up = inputState.isSet('cannonUp') down = inputState.isSet('cannonDown') left = inputState.isSet('cannonLeft') right = inputState.isSet('cannonRight') dt = globalClock.getDt() upAmount = 30 * dt downAmount = 45 * dt leftAmount = 45 * dt rightAmount = 45 * dt if up: self.cannon.find(self.cannonBarrel).setP(self.cannon.find(self.cannonBarrel).getP() + upAmount) elif down: self.cannon.find(self.cannonBarrel).setP(self.cannon.find(self.cannonBarrel).getP() - downAmount) if left: self.cannon.find(self.cannonBarrel).setH(self.cannon.find(self.cannonBarrel).getH() + leftAmount) elif right: self.cannon.find(self.cannonBarrel).setH(self.cannon.find(self.cannonBarrel).getH() - rightAmount) if up or down or left or right: if self.cannonMoveSfx.status() == self.cannonMoveSfx.READY: base.playSfx(self.cannonMoveSfx) elif self.cannonMoveSfx.status() == self.cannonMoveSfx.PLAYING: self.cannonMoveSfx.stop() return task.cont def exitControlCannon(self): self.ignore('control') taskMgr.remove('DEagleGame-handleCannonControls') taskMgr.remove('DEagleGame-broadcastCannonAndLT') for token in self.cist: token.release() del self.cist del self.cannon def controlKeyPressed(self): self.cannon.d_shoot() self.cannon.shoot() self.cannonFSM.request('fly') def __handleEagleHit(self, eagleId): self.toonOof.play() self.hitEagleSfx.play() self.sendUpdate('hitEagle', [eagleId]) def enterFly(self): self.acceptOnce(EGG.EAGLE_HIT_EVENT, self.__handleEagleHit) self.__setupCamera() cannon = self.cr.doId2do.get(self.cannonId) base.localAvatar.b_lookAtObject(0, 0, 0, blink=0) base.localAvatar.b_setAnimState('swim') dummyNode = NodePath('dummyNode') dummyNode.reparentTo(base.localAvatar) dummyNode.setPos(0, 160, -90) base.localAvatar.setPos(base.localAvatar.getPos(render)) base.localAvatar.setHpr(cannon.find(self.cannonBarrel).getHpr(render)) base.localAvatar.reparentTo(render) self.flyProjectile = FlightProjectileInterval(base.localAvatar, startPos=cannon.find(self.cannonBarrel).getPos(render) + (0, 5.0, 0), endPos=dummyNode.getPos(render), duration=5.0, name='DEagleGame-localAvatarFly', gravityMult=0.25) self.flyProjectile.setDoneEvent(self.flyProjectile.getName()) self.acceptOnce(self.flyProjectile.getDoneEvent(), self.__handleMissedEagle) self.flyProjectile.start() dummyNode.removeNode() del dummyNode self.cannonId = None del cannon base.localAvatar.startPosHprBroadcast() base.localAvatar.d_broadcastPositionNow() return def __handleMissedEagle(self): base.playSfx(self.fallSfx) self.sendUpdate('missedEagle', []) def exitFly(self): self.ignore(EGG.EAGLE_HIT_EVENT) self.ignore(self.flyProjectile.getDoneEvent()) self.flyProjectile.pause() del self.flyProjectile def __setupCamera(self, inCannon = 0): if inCannon: cannon = self.cr.doId2do.get(self.cannonId) camera.reparentTo(cannon) else: camera.reparentTo(base.localAvatar) camera.setPos(0.0, -14.75, 6.33) camera.setP(356.82) def enterPlay(self): DistributedMinigame.enterPlay(self) self.music.setPlayRate(self.Round2MusicSpeed[self.getRound()]) self.createTimer() if self.cannonId != None: self.cannonFSM.request('control') return def exitPlay(self): self.cannonFSM.request('off') self.deleteTimer() DistributedMinigame.exitPlay(self) def enterCannon(self, cannonId): self.cannonId = cannonId self.cannon = self.cr.doId2do.get(cannonId) base.localAvatar.stopPosHprBroadcast() base.localAvatar.d_clearSmoothing() self.broadcastLTPos() base.localAvatar.reparentTo(self.cannon.find(self.cannonBarrel)) base.localAvatar.setPosHpr(0, 3.5, 0, 90, -90, 90) base.localAvatar.b_setAnimState('neutral') base.localAvatar.b_lookAtObject(0, 90, 0, blink=0) base.localAvatar.animFSM.request('off') self.broadcastLTPos() if self.fsm.getCurrentState().getName() == 'play': self.cannonFSM.request('control') else: self.__setupCamera(1) def startRound(self, roundNum): self.round = roundNum self.fsm.request('roundCountdown', [roundNum]) def getRound(self): return self.round def enterRoundCountdown(self, roundNum): self.text = getGameText() self.track = Sequence(Func(self.text.setText, 'Round {0}'.format(roundNum)), getRoundIval(self.text), Func(self.text.setText, '3'), getCountdownIval(self.text), Func(self.text.setText, '2'), getCountdownIval(self.text), Func(self.text.setText, '1'), getCountdownIval(self.text), Func(self.fsm.request, 'play')) self.track.start() def exitRoundCountdown(self): self.track.pause() del self.track self.text.destroy() del self.text def enterRoundOver(self): self.text = getGameText() self.track = Sequence(Func(self.text.setText, "Time's Up!"), getRoundIval(self.text), Func(base.transitions.fadeOut, 1.0), Wait(2.0), Func(base.transitions.fadeIn, 1.0)) self.track.start() def exitRoundOver(self): self.track.pause() del self.track self.text.destroy() del self.text def allPlayersReady(self): self.waitLbl.hide() def load(self): self.hitEagleSfx = base.loadSfx('phase_4/audio/sfx/AA_drop_anvil_miss.mp3') self.hitObstacleSfx = base.loadSfx('phase_4/audio/sfx/MG_cannon_hit_tower.mp3') self.toonOof = base.loadSfx('phase_5/audio/sfx/tt_s_ara_cfg_toonHit.mp3') self.cannonMoveSfx = base.loadSfx('phase_4/audio/sfx/MG_cannon_adjust.mp3') self.cannonMoveSfx.setLoop(True) self.fallSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_fall.mp3') self.setMinigameMusic('phase_9/audio/bgm/CHQ_FACT_bg.mid') self.setDescription('Shoot as many flying Legal Eagles as you can using your cannon. Use the arrow keys to aim your cannon and press the control key to fire.') self.setWinnerPrize(60) self.setLoserPrize(20) base.setBackgroundColor(*self.bgColor) self.world = loader.loadModel(self.worldModelPath) for nodeName in self.nodesToStash: node = self.world.find('**/' + nodeName) node.removeNode() self.world.find('**/tt_m_ara_cfg_clump7:clump7').setY(30.0) self.world.find('**/tt_m_ara_cfg_eagleNest:eagleNest_mesh').setY(30.0) self.world.setColorScale(0.75, 0.75, 0.75, 1.0) self.world.reparentTo(base.render) self.world.setZ(-5.0) for i in range(len(self.platformPositions.keys())): platform = loader.loadModel('phase_9/models/cogHQ/platform1.bam') platform.find('**/platformcollision').removeNode() platform.reparentTo(render) platform.setPos(*self.platformPositions[i]) self.platforms.append(platform) for triggerName in self.triggers: trigger = self.world.find('**/' + triggerName) trigger.setCollideMask(CIGlobals.WallBitmask) self.accept('enter' + triggerName, self.__handleHitWall) self.fog = Fog('DEagleGame-sceneFog') self.fog.setColor(*self.bgColor) self.fog.setExpDensity(0.01) render.setFog(self.fog) DistributedMinigame.load(self) def __handleHitWall(self, entry): self.toonOof.play() self.hitObstacleSfx.play() self.sendUpdate('missedEagle') def playMinigameMusic(self): DistributedMinigame.playMinigameMusic(self) self.music.setVolume(0.3) def announceGenerate(self): DistributedMinigame.announceGenerate(self) base.localAvatar.disableChatInput() self.load() def disable(self): for triggerName in self.triggers: self.ignore('enter' + triggerName) base.localAvatar.createChatInput() camera.reparentTo(render) camera.setPosHpr(0, 0, 0, 0, 0, 0) render.clearFog() self.triggers = None self.toonOof = None self.hitEagleSfx = None self.hitObstacleSfx = None self.cannonMoveSfx = None self.fallSfx = None if self.world: self.world.removeNode() self.world = None self.worldModelPath = None self.nodesToStash = None self.fog = None self.round = None for platform in self.platforms: platform.removeNode() self.platforms = None self.cannonId = None self.cannonBarrel = None self.platformPositions = None base.setBackgroundColor(CIGlobals.DefaultBackgroundColor) self.bgColor = None DistributedMinigame.disable(self) return
class DistributedRaceGame(DistributedMinigame.DistributedMinigame): def __init__(self, cr): try: self.DistributedRaceGame_initialized return except: self.DistributedRaceGame_initialized = 1 DistributedMinigame.DistributedMinigame.__init__(self, cr) self.movement = RaceGameMovement.RaceGameMovement(base.localAvatar) self.skyUtil = SkyUtil() self.raceFSM = ClassicFSM('DistributedRaceGame', [State('race', self.enterRace, self.exitRace), State('raceTransition', self.enterRaceTransition, self.exitRaceTransition), State('off', self.enterRaceOff, self.exitRaceOff)], 'off', 'off') self.raceFSM.enterInitialState() self.cr = cr self.track = None self.sky = None self.countSfx = base.loadSfx('phase_5/audio/sfx/firehydrant_popup.mp3') self.goSfx = base.loadSfx('phase_4/audio/sfx/AA_sound_whistle.mp3') self.game = CIGlobals.RaceGame self.trackPath = 'phase_4/models/minigames/sprint_track.egg' self.skyPath = 'phase_3.5/models/props/TT_sky.bam' self.lanePos = [(-22.0, -205.0, 0.0), (-11.66, -205.0, 0.0), (0.0, -205.0, 0.0), (-33.66, -205.0, 0.0)] self.initialCamPos = {'pos': (41.1, -145.0, 25.88), 'hpr': (135.0, 345.96, 0.0)} self.raceCamPos = (-24.52, -37.22, 25.0) self.lane = 0 return def load(self): self.deleteWorld() self.track = loader.loadModel(self.trackPath) self.track.reparentTo(render) self.sky = loader.loadModel(self.skyPath) self.sky.reparentTo(self.track) self.skyUtil.startSky(self.sky) self.setMinigameMusic('phase_4/audio/bgm/MG_toontag.mid') self.setDescription('Tap the left and right arrow keys repeatedly, in turns, as fast as ' + 'you can to win the race! Every time your power bar hits the top, the boost bar starts' + ' to fill. When the boost bar is full, press CTRL to boost for a few seconds.') self.setWinnerPrize(20) self.setLoserPrize(5) self.d_requestToonLane() camera.reparentTo(render) camera.setPos(self.initialCamPos['pos']) camera.setHpr(self.initialCamPos['hpr']) DistributedMinigame.DistributedMinigame.load(self) def enterPlay(self): DistributedMinigame.DistributedMinigame.enterPlay(self) self.raceFSM.request('raceTransition') def exitPlay(self): DistributedMinigame.DistributedMinigame.exitPlay(self) self.raceFSM.request('off') def enterRace(self): self.startMovement() def exitRace(self): self.stopMovement() def enterRaceOff(self): pass def exitRaceOff(self): pass def enterRaceTransition(self): self.raceTrans = Sequence(Wait(0.5), Func(self.moveCameraToToon), Wait(4.5), Func(self.moveCameraToTop), Wait(4.5), Func(self.startCountdown)) self.raceTrans.start() def exitRaceTransition(self): self.raceTrans.pause() del self.raceTrans def startMovement(self): self.movement.createGui() self.movement.fsm.request('run') def enterGameOver(self, winner = 0, winnerDoId = 0, allPrize = 0): self.raceFSM.request('off') DistributedMinigame.DistributedMinigame.enterGameOver(self, winner, winnerDoId, allPrize) def stopMovement(self): self.movement.cleanup() self.movement.deleteGui() def startCountdown(self): """ Start the countdown to the start of the race. """ self.countdownLbl = DirectLabel(text='', text_scale=0.3, text_font=CIGlobals.getMickeyFont(), text_fg=(1, 1, 0, 1), pos=(0, 0, 0.5)) Sequence(Func(self.setCountdownText, '3'), Wait(1.0), Func(self.setCountdownText, '2'), Wait(1.0), Func(self.setCountdownText, '1'), Wait(1.0), Func(self.setCountdownText, 'GO!'), Wait(1.5), Func(self.deleteCountdownLabel)).start() def setCountdownText(self, number): self.countdownLbl['text'] = number if number == 'GO!': self.countdownLbl['text_fg'] = (0, 1, 0, 1) self.goSfx.play() self.raceFSM.request('race') else: self.countSfx.play() def deleteCountdownLabel(self): self.countdownLbl.destroy() del self.countdownLbl def moveCameraToToon(self): camPInt = LerpPosInterval(camera, duration=3.0, pos=self.localAv.getPos(render) + (0, 15, 3), startPos=camera.getPos(render), blendType='easeInOut') camQInt = camera.quatInterval(3.0, hpr=Vec3(180, 0, 0), blendType='easeInOut') camPInt.start() camQInt.start() def moveCameraToTop(self): camera.setPos(camera.getPos(self.localAv)) camera.reparentTo(self.localAv) oldPos = camera.getPos() camera.setPos(self.raceCamPos) oldHpr = camera.getHpr() camera.lookAt(self.localAv.getPart('head')) newHpr = camera.getHpr() camera.setHpr(oldHpr) camera.setPos(oldPos) camPInt = LerpPosInterval(camera, duration=3.0, pos=self.raceCamPos, startPos=oldPos, blendType='easeInOut') camQInt = camera.quatInterval(3.0, hpr=newHpr, blendType='easeInOut') camPInt.start() camQInt.start() def deleteWorld(self): if self.track: self.track.removeNode() self.track = None if self.sky: self.skyUtil.stopSky() self.sky.removeNode() self.sky = None return def setToonLane(self, lane): self.lane = lane base.localAvatar.setPos(self.lanePos[lane]) base.localAvatar.setHpr(0, 0, 0) def getToonLane(self): return self.lane def d_requestToonLane(self): self.sendUpdate('requestToonLane', []) def announceGenerate(self): DistributedMinigame.DistributedMinigame.announceGenerate(self) self.load() def disable(self): DistributedMinigame.DistributedMinigame.disable(self) self.deleteWorld() self.raceFSM.requestFinalState() del self.raceFSM self.countSfx = None self.goSfx = None return
class ShtickerBook(StateData): def __init__(self, parentFSM, doneEvent): self.parentFSM = parentFSM StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('ShtickerBook', [State('off', self.enterOff, self.exitOff), State('optionPage', self.enterOptionPage, self.exitOptionPage, ['districtPage', 'off']), State('districtPage', self.enterDistrictPage, self.exitDistrictPage, ['optionPage', 'questPage', 'off']), State('questPage', self.enterQuestPage, self.exitQuestPage, ['inventoryPage', 'districtPage', 'off']), State('inventoryPage', self.enterInventoryPage, self.exitInventoryPage, ['mapPage', 'questPage', 'off']), State('mapPage', self.enterMapPage, self.exitMapPage, ['releaseNotesPage', 'inventoryPage', 'off']), State('releaseNotesPage', self.enterReleaseNotesPage, self.exitReleaseNotesPage, ['mapPage', 'off']), State('adminPage', self.enterAdminPage, self.exitAdminPage, ['releaseNotesPage', 'off'])], 'off', 'off') if base.localAvatar.getAdminToken() > -1: self.fsm.getStateNamed('releaseNotesPage').addTransition('adminPage') self.fsm.enterInitialState() self.entered = 0 self.parentFSM.getStateNamed('shtickerBook').addChild(self.fsm) def enterOff(self): pass def exitOff(self): pass def load(self): StateData.load(self) self.book_contents = loader.loadModel('phase_3.5/models/gui/stickerbook_gui.bam') self.book_texture = self.book_contents.find('**/big_book') self.book_open = loader.loadSfx('phase_3.5/audio/sfx/GUI_stickerbook_open.mp3') self.book_close = loader.loadSfx('phase_3.5/audio/sfx/GUI_stickerbook_delete.mp3') self.book_turn = loader.loadSfx('phase_3.5/audio/sfx/GUI_stickerbook_turn.mp3') def unload(self): self.book_texture.removeNode() del self.book_texture self.book_contents.removeNode() del self.book_contents loader.unloadSfx(self.book_open) del self.book_open loader.unloadSfx(self.book_close) del self.book_close loader.unloadSfx(self.book_turn) del self.book_turn del self.fsm del self.parentFSM del self.entered StateData.unload(self) def enter(self): if self.entered: return self.entered = 1 StateData.enter(self) render.hide() base.setBackgroundColor(0.05, 0.15, 0.4) self.book_img = OnscreenImage(image=self.book_texture, scale=(2, 1, 1.5)) self.book_open.play() if base.localAvatar.getAdminToken() > -1: self.fsm.request('adminPage') else: self.fsm.request('mapPage') def exit(self): if not self.entered: return self.entered = 0 base.setBackgroundColor(CIGlobals.DefaultBackgroundColor) render.show() self.book_img.destroy() del self.book_img self.book_close.play() self.fsm.request('off') StateData.exit(self) def enterDistrictPage(self): self.createPageButtons('optionPage', 'questPage') self.setTitle('Districts') currDistrictName = base.cr.myDistrict.getDistrictName() if not currDistrictName.isalpha(): currDistrictName = currDistrictName[:-1] self.infoLbl = OnscreenText(text='Each District is a copy of the Cog Invasion world.\n\n\nYou are currently in the "%s" District' % currDistrictName, pos=(0.05, 0.3), align=TextNode.ALeft, wordwrap=12) self.populationLbl = OnscreenText(text='Population: %d' % base.cr.myDistrict.getPopulation(), pos=(0.44, -0.3), align=TextNode.ACenter) textRolloverColor = Vec4(1, 1, 0, 1) textDownColor = Vec4(0.5, 0.9, 1, 1) textDisabledColor = Vec4(0.4, 0.8, 0.4, 1) self.shardButtons = [] for shard in base.cr.activeDistricts.values(): shardName = shard.getDistrictName() shardId = shard.doId btn = DirectButton(relief=None, text=shardName, text_scale=0.07, text_align=TextNode.ALeft, text1_bg=textDownColor, text2_bg=textRolloverColor, text3_fg=textDisabledColor, textMayChange=0, command=self.__handleShardButton, extraArgs=[shardId], text_pos=(0, 0, 0.0)) if shardId == base.localAvatar.parentId: btn['state'] = DGG.DISABLED else: btn['state'] = DGG.NORMAL self.shardButtons.append(btn) gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam') listXorigin = -0.02 listFrameSizeX = 0.625 listZorigin = -0.96 listFrameSizeZ = 1.04 arrowButtonScale = 1.3 itemFrameXorigin = -0.237 itemFrameZorigin = 0.365 buttonXstart = itemFrameXorigin + 0.293 self.districtList = DirectScrolledList(relief=None, pos=(-0.54, 0, 0.08), incButton_image=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), incButton_relief=None, incButton_scale=(arrowButtonScale, arrowButtonScale, -arrowButtonScale), incButton_pos=(buttonXstart, 0, itemFrameZorigin - 0.999), incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), decButton_relief=None, decButton_scale=(arrowButtonScale, arrowButtonScale, arrowButtonScale), decButton_pos=(buttonXstart, 0, itemFrameZorigin + 0.125), decButton_image3_color=Vec4(1, 1, 1, 0.2), itemFrame_pos=(itemFrameXorigin, 0, itemFrameZorigin), itemFrame_scale=1.0, itemFrame_relief=DGG.SUNKEN, itemFrame_frameSize=(listXorigin, listXorigin + listFrameSizeX, listZorigin, listZorigin + listFrameSizeZ), itemFrame_frameColor=(0.85, 0.95, 1, 1), itemFrame_borderWidth=(0.01, 0.01), numItemsVisible=15, forceHeight=0.075, items=self.shardButtons) base.taskMgr.add(self.__updateDistrictPopTask, 'SB.updateDistrictPopTask') return def __handleShardButton(self, shardId): self.finished('switchShard', shardId) def __updateDistrictPopTask(self, task): population = base.cr.myDistrict.getPopulation() self.populationLbl.setText('Population: %d' % population) task.delayTime = 5.0 return task.again def exitDistrictPage(self): base.taskMgr.remove('SB.updateDistrictPopTask') for btn in self.shardButtons: btn.destroy() del self.shardButtons self.districtList.destroy() del self.districtList self.infoLbl.destroy() del self.infoLbl self.populationLbl.destroy() del self.populationLbl self.deletePageButtons(True, True) self.clearTitle() def enterQuestPage(self): self.createPageButtons('districtPage', 'inventoryPage') self.setTitle('Quests') self.notes = base.localAvatar.questManager.makeQuestNotes() for note in self.notes: note.show() self.infoText = OnscreenText(text='Return completed Quests to an HQ Officer at any Toon HQ building.', pos=(0, -0.6), scale=0.045) def exitQuestPage(self): self.infoText.destroy() del self.infoText for note in self.notes: note.destroy() self.deletePageButtons(True, True) self.clearTitle() def enterInventoryPage(self): self.createPageButtons('questPage', 'mapPage') self.setTitle('Gags') self.gui = BackpackGUI() self.gui.createGUI() def exitInventoryPage(self): self.gui.deleteGUI() del self.gui self.deletePageButtons(True, True) self.clearTitle() def enterMapPage(self): self.createPageButtons('inventoryPage', 'releaseNotesPage') self.setTitle('') themap = loader.loadModel('phase_3.5/models/gui/toontown_map.bam') self.frame = DirectFrame(parent=aspect2d, relief=None, image=themap, image_scale=(1.8, 1, 1.35), scale=0.97, pos=(0, 0, 0.0775)) cloudpos = [[(-0.61, 0, 0.18), (0.55, 0.25, 0.37), (180, 0, 0)], [(-0.54, 0, 0.34), (0.76, 0.4, 0.55), (180, 0, 0)], [(-0.55, 0, -0.09), (0.72, 0.4, 0.55), (0, 0, 0)], [(-0.67, 0, -0.51), (0.5, 0.29, 0.38), (180, 0, 0)], [(-0.67, 0, 0.51), (0.5, 0.29, 0.38), (0, 0, 0)], [(0.67, 0, 0.51), (0.5, 0.29, 0.38), (0, 0, 0)], [(0.35, 0, -0.46), (0.63, 0.35, 0.45), (0, 0, 0)], [(0.18, 0, -0.45), (0.52, 0.27, 0.32), (0, 0, 0)], [(0.67, 0, -0.44), (0.63, 0.35, 0.48), (180, 0, 0)]] hoodclouds = [[(0.63, 0, -0.13), (0.63, 0.35, 0.4), (0, 0, 0), CIGlobals.DonaldsDock], [(0.51, 0, 0.25), (0.57, 0.35, 0.4), (0, 0, 0), CIGlobals.TheBrrrgh], [(0.03, 0, 0.19), (0.63, 0.35, 0.4), (180, 0, 0), CIGlobals.MinniesMelodyland], [(-0.08, 0, 0.46), (0.54, 0.35, 0.4), (0, 0, 0), CIGlobals.DonaldsDreamland], [(-0.28, 0, -0.49), (0.6, 0.35, 0.45), (0, 0, 0), CIGlobals.DaisyGardens]] self.clouds = [] self.labels = [] for pos, scale, hpr in cloudpos: cloud = loader.loadModel('phase_3.5/models/gui/cloud.bam') cloud.reparentTo(self.frame) cloud.setPos(pos) cloud.setScale(scale) cloud.setHpr(hpr) self.clouds.append(cloud) for pos, scale, hpr, hood in hoodclouds: if not base.localAvatar.hasDiscoveredHood(ZoneUtil.getZoneId(hood)): cloud = loader.loadModel('phase_3.5/models/gui/cloud.bam') cloud.reparentTo(self.frame) cloud.setPos(pos) cloud.setScale(scale) cloud.setHpr(hpr) self.clouds.append(cloud) labeldata = [[(0, 0, -0.2), CIGlobals.ToontownCentral], [(0.65, 0, -0.125), CIGlobals.DonaldsDock], [(0.07, 0, 0.18), CIGlobals.MinniesMelodyland], [(-0.1, 0, 0.45), CIGlobals.DonaldsDreamland], [(0.5, 0, 0.25), CIGlobals.TheBrrrgh], [(-0.37, 0, -0.525), CIGlobals.DaisyGardens]] for pos, name in labeldata: if base.localAvatar.hasDiscoveredHood(ZoneUtil.getZoneId(name)): text = name if base.localAvatar.hasTeleportAccess(ZoneUtil.getZoneId(name)): text = 'Go To\n' + text label = DirectButton(parent=self.frame, relief=None, pos=pos, pad=(0.2, 0.16), text=('', text, text), text_bg=Vec4(1, 1, 1, 0.4), text_scale=0.055, text_wordwrap=8, rolloverSound=None, clickSound=None, pressEffect=0, sortOrder=1, text_font=CIGlobals.getToonFont()) if base.localAvatar.hasTeleportAccess(ZoneUtil.getZoneId(name)): label['command'] = self.finished label['extraArgs'] = [ZoneUtil.getZoneId(name)] label.resetFrameSize() self.labels.append(label) currHoodName = base.cr.playGame.hood.id currLocation = '' if base.localAvatar.zoneId == CIGlobals.MinigameAreaId: currLocation = '' elif base.localAvatar.getMyBattle() != None: currLocation = 'CogTropolis' elif ZoneUtil.getWhereName(base.localAvatar.zoneId) == 'playground': currLocation = 'Playground' elif ZoneUtil.getWhereName(base.localAvatar.zoneId) in ('street', 'interior'): currLocation = CIGlobals.BranchZone2StreetName[ZoneUtil.getBranchZone(base.localAvatar.zoneId)] self.infoLabel = DirectLabel(relief=None, text='You are in: {0}\n{1}'.format(currHoodName, currLocation), scale=0.06, pos=(-0.4, 0, -0.74), parent=self.frame, text_align=TextNode.ACenter) if currHoodName in [CIGlobals.MinigameArea, CIGlobals.BattleTTC]: currHoodName = base.cr.playGame.lastHood self.BTPButton = DirectButton(relief=None, text='Back to Playground', geom=CIGlobals.getDefaultBtnGeom(), text_pos=(0, -0.018), geom_scale=(1.3, 1.11, 1.11), text_scale=0.06, parent=self.frame, text_font=CIGlobals.getToonFont(), pos=(0.25, 0, -0.75), command=self.finished, extraArgs=[ZoneUtil.getZoneId(currHoodName)], scale=0.7) if base.localAvatar.zoneId != CIGlobals.MinigameAreaId: self.MGAButton = DirectButton(relief=None, text='Minigame Area', geom=CIGlobals.getDefaultBtnGeom(), text_pos=(0, -0.018), geom_scale=(1, 1.11, 1.11), text_scale=0.06, parent=self.frame, text_font=CIGlobals.getToonFont(), pos=(0.625, 0, -0.75), command=self.finished, extraArgs=[CIGlobals.MinigameAreaId], scale=0.7) return def exitMapPage(self): for label in self.labels: label.destroy() del self.labels for cloud in self.clouds: cloud.removeNode() del self.clouds self.frame.destroy() del self.frame self.infoLabel.destroy() del self.infoLabel self.BTPButton.destroy() del self.BTPButton if hasattr(self, 'MGAButton'): self.MGAButton.destroy() del self.MGAButton self.deletePageButtons(True, True) self.clearTitle() def enterZonePage(self): self.createPageButtons('inventoryPage', 'releaseNotesPage') self.setTitle('Places') self.ttc_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.045, text=CIGlobals.ToontownCentral, command=self.finished, extraArgs=[CIGlobals.ToontownCentralId], pos=(-0.45, 0.15, 0.5), text_pos=(0, -0.01)) self.tbr_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.055, text=CIGlobals.TheBrrrgh, command=self.finished, extraArgs=[CIGlobals.TheBrrrghId], pos=(-0.45, 0.15, 0.38), text_pos=(0, -0.01)) self.ddl_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.044, text=CIGlobals.DonaldsDreamland, command=self.finished, extraArgs=[CIGlobals.DonaldsDreamlandId], pos=(-0.45, 0.15, 0.26), text_pos=(0, -0.01)) self.mml_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.0425, text=CIGlobals.MinniesMelodyland, command=self.finished, extraArgs=[CIGlobals.MinniesMelodylandId], pos=(-0.45, 0.35, 0.14), text_pos=(0, -0.01)) self.dg_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.045, text=CIGlobals.DaisyGardens, command=self.finished, extraArgs=[CIGlobals.DaisyGardensId], pos=(-0.45, 0.35, 0.02), text_pos=(0, -0.01)) self.dd_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.045, text=CIGlobals.DonaldsDock, command=self.finished, extraArgs=[CIGlobals.DonaldsDockId], pos=(-0.45, 0.35, -0.1), text_pos=(0, -0.01)) self.minigame_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.055, text=CIGlobals.MinigameArea, command=self.finished, extraArgs=[CIGlobals.MinigameAreaId], pos=(-0.45, 0.35, -0.34), text_pos=(0, -0.01)) return def __updateGamePopulation(self, task): population = 0 for district in base.cr.activeDistricts.values(): population += district.getPopulation() self.populationLbl.setText('Game Population:\n' + str(population)) recordPopulation = base.cr.myDistrict.getPopRecord() self.popRecordLbl.setText('Record Population:\n' + str(recordPopulation)) task.delayTime = 5.0 return task.again def exitZonePage(self): self.dd_btn.destroy() del self.dd_btn self.ddl_btn.destroy() del self.ddl_btn self.ttc_btn.destroy() del self.ttc_btn self.tbr_btn.destroy() del self.tbr_btn self.minigame_btn.destroy() del self.minigame_btn self.mml_btn.destroy() del self.mml_btn self.dg_btn.destroy() del self.dg_btn self.deletePageButtons(True, True) self.clearTitle() def createPageButtons(self, back, fwd): if back: self.btn_prev = DirectButton(geom=(self.book_contents.find('**/arrow_button'), self.book_contents.find('**/arrow_down'), self.book_contents.find('**/arrow_rollover')), relief=None, pos=(-0.838, 0, -0.661), scale=(-0.1, 0.1, 0.1), command=self.pageDone, extraArgs=[back]) if fwd: self.btn_next = DirectButton(geom=(self.book_contents.find('**/arrow_button'), self.book_contents.find('**/arrow_down'), self.book_contents.find('**/arrow_rollover')), relief=None, pos=(0.838, 0, -0.661), scale=(0.1, 0.1, 0.1), command=self.pageDone, extraArgs=[fwd]) return def deletePageButtons(self, back, fwd): if back: self.btn_prev.destroy() del self.btn_prev if fwd: self.btn_next.destroy() del self.btn_next def setTitle(self, title): self.page_title = OnscreenText(text=title, pos=(0, 0.62, 0), scale=0.12) def clearTitle(self): self.page_title.destroy() del self.page_title def enterReleaseNotesPage(self): if base.localAvatar.getAdminToken() > -1: self.createPageButtons('mapPage', 'adminPage') else: self.createPageButtons('mapPage', None) self.setTitle('Release Notes') self.frame = DirectScrolledFrame(canvasSize=(-1, 1, -3.5, 1), frameSize=(-1, 1, -0.6, 0.6)) self.frame.setPos(0, 0, 0) self.frame.setScale(0.8) self.release_notes = DirectLabel(text=open('release_notes.txt', 'r').read(), text_align=TextNode.ALeft, pos=(-0.955, 0, 0.93), relief=None, text_fg=(0, 0, 0, 1), text_wordwrap=37.0, text_scale=0.05, parent=self.frame.getCanvas()) return def exitReleaseNotesPage(self): self.frame.destroy() del self.frame self.release_notes.destroy() del self.release_notes self.clearTitle() if base.localAvatar.getAdminToken() > -1: self.deletePageButtons(True, True) else: self.deletePageButtons(True, False) def enterAdminPage(self): self.adminPageStateData = AdminPage(self, self.fsm) self.adminPageStateData.load() self.adminPageStateData.enter() def exitAdminPage(self): self.adminPageStateData.exit() self.adminPageStateData.unload() del self.adminPageStateData def pageDone(self, nextPage): self.fsm.request(nextPage) self.book_turn.play() def enterOptionPage(self): self.optionPageStateData = OptionPage(self, self.fsm) self.optionPageStateData.load() self.optionPageStateData.enter() def exitOptionPage(self): self.optionPageStateData.exit() self.optionPageStateData.unload() del self.optionPageStateData def prevPage(self, currentPage): self.clearCurrentPage() if self.currentPage == 2: self.optionPage() elif self.currentPage == 3: self.zonePage() elif self.currentPage == 4: self.releaseNotesPage() def nextPage(self, currentPage): self.clearCurrentPage() if self.currentPage == 1: self.zonePage() elif self.currentPage == 2: self.releaseNotesPage() elif self.currentPage == 3: self.adminPage() def clearCurrentPage(self): self.book_turn.play() for m in base.bookpgnode.getChildren(): m.removeNode() def finished(self, zone, shardId = None): if base.localAvatar.getHealth() < 1 and type(zone) == type(1): return else: doneStatus = {} if zone in [CIGlobals.ToontownCentralId, CIGlobals.MinigameAreaId, CIGlobals.TheBrrrghId, CIGlobals.DonaldsDreamlandId, CIGlobals.MinniesMelodylandId, CIGlobals.DaisyGardensId, CIGlobals.DonaldsDockId]: doneStatus['mode'] = 'teleport' doneStatus['zoneId'] = zone doneStatus['hoodId'] = ZoneUtil.getHoodId(zone) doneStatus['where'] = ZoneUtil.getWhereName(zone) doneStatus['how'] = 'teleportIn' doneStatus['avId'] = base.localAvatar.doId doneStatus['shardId'] = None doneStatus['loader'] = ZoneUtil.getLoaderName(zone) else: doneStatus['mode'] = zone if zone == 'switchShard': doneStatus['shardId'] = shardId self.doneStatus = doneStatus messenger.send(self.doneEvent) return def closeBook(self): self.book_close.play() base.bookpgnode.removeNode() base.booknode.removeNode()
class SafeZoneLoader(StateData): notify = directNotify.newCategory('SafeZoneLoader') def __init__(self, hood, parentFSMState, doneEvent): StateData.__init__(self, doneEvent) self.hood = hood self.parentFSMState = parentFSMState self.fsm = ClassicFSM('safeZoneLoader', [State('off', self.enterOff, self.exitOff), State('playground', self.enterPlayground, self.exitPlayground, ['quietZone']), State('toonInterior', self.enterToonInterior, self.exitToonInterior, ['quietZone']), State('quietZone', self.enterQuietZone, self.exitQuietZone, ['playground', 'toonInterior'])], 'off', 'off') self.placeDoneEvent = 'placeDone' self.place = None self.playground = None self.battleMusic = None self.invasionMusic = None self.invasionMusicFiles = None self.interiorMusic = None self.bossBattleMusic = None self.music = None self.tournamentMusic = None self.linkTunnels = [] return def findAndMakeLinkTunnels(self): for tunnel in self.geom.findAllMatches('**/*linktunnel*'): dnaRootStr = tunnel.getName() link = LinkTunnel.SafeZoneLinkTunnel(tunnel, dnaRootStr) self.linkTunnels.append(link) def load(self): StateData.load(self) if self.pgMusicFilename: self.music = base.loadMusic(self.pgMusicFilename) if self.battleMusicFile: self.battleMusic = base.loadMusic(self.battleMusicFile) if self.invasionMusicFiles: self.invasionMusic = None if self.bossBattleMusicFile: self.bossBattleMusic = base.loadMusic(self.bossBattleMusicFile) if self.interiorMusicFilename: self.interiorMusic = base.loadMusic(self.interiorMusicFilename) if self.tournamentMusicFiles: self.tournamentMusic = None self.createSafeZone(self.dnaFile) self.parentFSMState.addChild(self.fsm) width, height, fs, music, sfx, tex_detail, model_detail, aa, af = SettingsManager().getSettings('settings.json') if af == 'on': self.notify.info('Anisotropic Filtering is on, applying to textures.') for nodepath in self.geom.findAllMatches('*'): try: for node in nodepath.findAllMatches('**'): try: node.findTexture('*').setAnisotropicDegree(8) except: pass except: continue return def unload(self): StateData.unload(self) self.parentFSMState.removeChild(self.fsm) del self.parentFSMState self.geom.removeNode() del self.geom del self.fsm del self.hood del self.playground del self.music del self.interiorMusic del self.battleMusic del self.bossBattleMusic del self.tournamentMusic self.ignoreAll() ModelPool.garbageCollect() TexturePool.garbageCollect() def enter(self, requestStatus): StateData.enter(self) if base.localAvatar.zoneId < 61000: self.findAndMakeLinkTunnels() self.fsm.enterInitialState() messenger.send('enterSafeZone') self.setState(requestStatus['where'], requestStatus) partyGate = self.geom.find('**/prop_party_gate_DNARoot') if not partyGate.isEmpty(): partyGate.removeNode() del partyGate petShop = self.geom.find('**/prop_pet_shop_DNARoot') if not petShop.isEmpty(): petShop.removeNode() del petShop def exit(self): StateData.exit(self) messenger.send('exitSafeZone') for link in self.linkTunnels: link.cleanup() self.linkTunnels = [] def setState(self, stateName, requestStatus): self.fsm.request(stateName, [requestStatus]) def createSafeZone(self, dnaFile): if self.szStorageDNAFile: loader.loadDNAFile(self.hood.dnaStore, self.szStorageDNAFile) node = loader.loadDNAFile(self.hood.dnaStore, dnaFile) if node.getNumParents() == 1: self.geom = NodePath(node.getParent(0)) self.geom.reparentTo(hidden) else: self.geom = hidden.attachNewNode(node) self.makeDictionaries(self.hood.dnaStore) if self.__class__.__name__ not in ('TTSafeZoneLoader',): self.geom.flattenMedium() gsg = base.win.getGsg() if gsg: self.geom.prepareScene(gsg) def makeDictionaries(self, dnaStore): self.nodeList = [] for i in xrange(dnaStore.getNumDNAVisGroups()): groupFullName = dnaStore.getDNAVisGroupName(i) groupName = base.cr.hoodMgr.extractGroupName(groupFullName) groupNode = self.geom.find('**/' + groupFullName) if groupNode.isEmpty(): self.notify.error('Could not find visgroup') if self.__class__.__name__ not in ('TTSafeZoneLoader',): groupNode.flattenMedium() self.nodeList.append(groupNode) self.hood.dnaStore.resetPlaceNodes() self.hood.dnaStore.resetDNAGroups() self.hood.dnaStore.resetDNAVisGroups() self.hood.dnaStore.resetDNAVisGroupsAI() def enterPlayground(self, requestStatus): try: self.hood.stopSuitEffect() except: pass self.acceptOnce(self.placeDoneEvent, self.handlePlaygroundDone) self.place = self.playground(self, self.fsm, self.placeDoneEvent) self.place.load() def exitPlayground(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) return def handlePlaygroundDone(self): status = self.place.doneStatus if self.hood.isSameHood(status) and status['loader'] == 'safeZoneLoader' and status['where'] not in ('minigame',): self.fsm.request('quietZone', [status]) else: self.doneStatus = status messenger.send(self.doneEvent) def enterToonInterior(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.handleToonInteriorDone) self.place = ToonInterior.ToonInterior(self, self.fsm, self.placeDoneEvent) self.place.load() def enterThePlace(self, requestStatus): base.cr.playGame.setPlace(self.place) self.place.enter(requestStatus) def exitToonInterior(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) return def handleToonInteriorDone(self): status = self.place.doneStatus if status['loader'] == 'safeZoneLoader' and self.hood.isSameHood(status) and status['shardId'] == None or status['how'] == 'doorOut': self.fsm.request('quietZone', [status]) else: self.doneStatus = status messenger.send(self.doneEvent) return def enterQuietZone(self, requestStatus): self.fsm.request(requestStatus['where'], [requestStatus], exitCurrent=0) self.quietZoneDoneEvent = uniqueName('quietZoneDone') self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone) self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent) self.quietZoneStateData.load() self.quietZoneStateData.enter(requestStatus) def exitQuietZone(self): self.ignore(self.quietZoneDoneEvent) del self.quietZoneDoneEvent self.quietZoneStateData.exit() self.quietZoneStateData.unload() self.quietZoneStateData = None return def handleQuietZoneDone(self): status = self.quietZoneStateData.getDoneStatus() self.exitQuietZone() if status['where'] == 'estate' or status['loader'] == 'townLoader': self.doneStatus = status messenger.send(self.doneEvent) else: self.enterThePlace(status) def enterOff(self): pass def exitOff(self): pass
class Playground(Place.Place): notify = directNotify.newCategory("Playground") def __init__(self, loader, parentFSM, doneEvent): Place.Place.__init__(self, loader, doneEvent) self.fsm = ClassicFSM('Playground', [ State( 'start', self.enterStart, self.exitStart, ['walk', 'teleportIn', 'tunnelOut', 'doorOut', 'trolleyOut']), State('teleportIn', self.enterTeleportIn, self.exitTeleportIn, ['walk', 'acknowledgeDeath']), State('walk', self.enterWalk, self.exitWalk, ['teleportOut', 'stop', 'shtickerBook', 'died', 'tunnelIn']), State('teleportOut', self.enterTeleportOut, self.exitTeleportOut, ['teleportIn', 'stop']), State('stop', self.enterStop, self.exitStop, ['walk', 'died', 'station', 'teleportOut', 'doorIn']), State('shtickerBook', self.enterShtickerBook, self.exitShtickerBook, ['teleportOut', 'walk']), State('tunnelOut', self.enterTunnelOut, self.exitTeleportOut, ['walk']), State('final', self.enterFinal, self.exitFinal, ['start']), State('died', self.enterDied, self.exitDied, ['final']), State('station', self.enterStation, self.exitStation, ['teleportOut', 'walk']), State('doorIn', self.enterDoorIn, self.exitDoorIn, ['stop']), State('doorOut', self.enterDoorOut, self.exitDoorOut, ['walk']), State('tunnelIn', self.enterTunnelIn, self.exitTunnelIn, ['stop']), State('acknowledgeDeath', self.enterAcknowledgeDeath, self.exitAcknowledgeDeath, ['walk']), State('trolleyOut', self.enterTrolleyOut, self.exitTrolleyOut, ['walk', 'stop']) ], 'start', 'final') self.parentFSM = parentFSM return def enter(self, requestStatus): self.fsm.enterInitialState() self.loader.hood.enableOutdoorLighting() messenger.send('enterPlayground') base.playMusic(self.loader.safeZoneSong) self.loader.geom.reparentTo(render) base.enablePhysicsNodes(self.loader.geom) #self.loader.hood.startSky() self.zoneId = requestStatus['zoneId'] if base.cr.playGame.suitManager: base.cr.playGame.suitManager.d_requestSuitInfo() how = requestStatus['how'] self.fsm.request(how, [requestStatus]) Place.Place.enter(self) def exit(self): self.ignoreAll() messenger.send('exitPlayground') self.loader.geom.reparentTo(hidden) base.disablePhysicsNodes(self.loader.geom) base.stopMusic() self.loader.hood.disableOutdoorLighting() Place.Place.exit(self) def load(self): Place.Place.load(self) self.parentFSM.getStateNamed('playground').addChild(self.fsm) def unload(self): self.parentFSM.getStateNamed('playground').removeChild(self.fsm) del self.parentFSM del self.fsm self.ignoreAll() Place.Place.unload(self) return def enterStation(self): pass def exitStation(self): pass def enterWalk(self, teleportIn=0, wantMouse=1): Place.Place.enterWalk(self, teleportIn, wantMouse) def enterTeleportIn(self, requestStatus): if base.localAvatar.getHealth() < 1: requestStatus['nextState'] = 'acknowledgeDeath' else: requestStatus['nextState'] = 'walk' x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId( self.loader.hood.id) dropLocation = self.loader.geom.attachNewNode('dropLocation') dropLocation.setPos(x, y, z) dropLocation.setHpr(h, p, r) base.localAvatar.gotoNode(dropLocation) base.localAvatar.setHpr(h, p, r) dropLocation.removeNode() Place.Place.enterTeleportIn(self, requestStatus) return
class BRWater: notify = directNotify.newCategory('BRWater') def __init__(self, playground): self.playground = playground self.fsm = ClassicFSM('BRWater', [State('off', self.enterOff, self.exitOff), State('freezeUp', self.enterFreezeUp, self.exitFreezeUp), State('coolDown', self.enterCoolDown, self.exitCoolDown), State('frozen', self.enterFrozen, self.exitFrozen)], 'off', 'off') self.fsm.enterInitialState() self.freezeUpSfx = base.loadSfx('phase_8/audio/sfx/freeze_up.mp3') self.frozenSfxArray = [base.loadSfx('phase_8/audio/sfx/frozen_1.mp3'), base.loadSfx('phase_8/audio/sfx/frozen_2.mp3'), base.loadSfx('phase_8/audio/sfx/frozen_3.mp3')] self.coolSfxArray = [base.loadSfx('phase_8/audio/sfx/cool_down_1.mp3'), base.loadSfx('phase_8/audio/sfx/cool_down_2.mp3')] self.freezeUpSfx.setVolume(12) for sfx in self.frozenSfxArray: sfx.setVolume(12) for sfx in self.coolSfxArray: sfx.setVolume(12) def attachSound(self, sound): base.localAvatar.audio3d.attachSoundToObject(sound, base.localAvatar) def enterOff(self): self.playground.startWaterWatch() def exitOff(self): self.playground.stopWaterWatch() def loadIceCube(self): self.iceCube = loader.loadModel('phase_8/models/props/icecube.bam') for node in self.iceCube.findAllMatches('**/billboard*'): node.removeNode() for node in self.iceCube.findAllMatches('**/drop_shadow*'): node.removeNode() for node in self.iceCube.findAllMatches('**/prop_mailboxcollisions*'): node.removeNode() self.iceCube.reparentTo(base.localAvatar) self.iceCube.setScale(1.2, 1.0, base.localAvatar.getHeight() / 1.7) self.iceCube.setTransparency(1) self.iceCube.setColorScale(0.76, 0.76, 1.0, 0.0) def unloadIceCube(self): self.iceCube.removeNode() del self.iceCube def enterFreezeUp(self): length = 1.0 base.playSfx(self.freezeUpSfx) self.fucsIval = Sequence(LerpColorScaleInterval(base.localAvatar.getGeomNode(), duration=length, colorScale=VBase4(0.5, 0.5, 1.0, 1.0), startColorScale=base.localAvatar.getGeomNode().getColorScale(), blendType='easeOut'), Func(self.fsm.request, 'frozen')) self.fucsIval.start() self.playground.startWaterWatch(0) def exitFreezeUp(self): self.fucsIval.pause() del self.fucsIval self.playground.stopWaterWatch() def enterFrozen(self): self.loadIceCube() base.cr.playGame.getPlace().fsm.request('stop', [0]) base.localAvatar.stop() base.playSfx(choice(self.frozenSfxArray)) self.iccsIval = LerpColorScaleInterval(self.iceCube, duration=0.5, colorScale=VBase4(0.76, 0.76, 1.0, 1.0), startColorScale=self.iceCube.getColorScale(), blendType='easeInOut') self.iccsIval.start() props = WindowProperties() props.setCursorHidden(True) base.win.requestProperties(props) self.frame = DirectFrame(pos=(0, 0, 0.7)) self.powerBar = DirectWaitBar(frameColor=(1, 1, 1, 1), range=100, value=0, scale=(0.4, 0.5, 0.25), parent=self.frame, barColor=(0.55, 0.7, 1.0, 1.0)) self.label = OnscreenText(text='SHAKE MOUSE', shadow=(0, 0, 0, 1), fg=(0.55, 0.7, 1.0, 1.0), pos=(0, -0.1, 0), parent=self.frame) taskMgr.add(self.__watchMouseMovement, 'BRWater-watchMouseMovement') taskMgr.add(self.__lowerPowerBar, 'BRWater-lowerPowerBar') mw = base.mouseWatcherNode if mw.hasMouse(): self.lastMouseX = mw.getMouseX() def __lowerPowerBar(self, task): if self.powerBar['value'] <= 0: self.powerBar.update(0) decrement = 1 self.powerBar.update(self.powerBar['value'] - decrement) task.delayTime = 0.1 return task.again def __watchMouseMovement(self, task): if self.powerBar['value'] >= self.powerBar['range']: self.fsm.request('coolDown', [1]) return task.done mw = base.mouseWatcherNode if mw.hasMouse(): if not self.lastMouseX or self.lastMouseX != mw.getMouseX(): value = 3 * self.lastMouseX - mw.getMouseX() self.lastMouseX = mw.getMouseX() self.powerBar.update(self.powerBar['value'] + abs(value)) return task.cont def exitFrozen(self): props = WindowProperties() props.setCursorHidden(False) base.win.requestProperties(props) self.iccsIval.pause() del self.iccsIval self.unloadIceCube() taskMgr.remove('BRWater-lowerPowerBar') taskMgr.remove('BRWater-watchMouseMovement') self.label.destroy() del self.label self.powerBar.destroy() del self.powerBar self.frame.destroy() del self.frame del self.lastMouseX base.cr.playGame.getPlace().fsm.request('walk') base.localAvatar.b_setAnimState('neutral') def enterCoolDown(self, fromFrozen = 0): if fromFrozen: self.loadIceCube() self.iceCube.setColorScale(0.76, 0.76, 1.0, 1.0) self.iccdIval = LerpColorScaleInterval(self.iceCube, duration=0.5, colorScale=VBase4(0.76, 0.76, 1.0, 0.0), startColorScale=self.iceCube.getColorScale(), blendType='easeInOut') self.iccdIval.start() length = 1.0 base.playSfx(choice(self.coolSfxArray)) self.cdcsIval = Sequence(LerpColorScaleInterval(base.localAvatar.getGeomNode(), duration=length, colorScale=VBase4(1.0, 1.0, 1.0, 1.0), startColorScale=base.localAvatar.getGeomNode().getColorScale(), blendType='easeOut'), Func(self.fsm.request, 'off')) self.cdcsIval.start() def exitCoolDown(self): if hasattr(self, 'iccdIval'): self.iccdIval.pause() del self.iccdIval self.unloadIceCube() self.cdcsIval.pause() del self.cdcsIval def cleanup(self): self.fsm.requestFinalState() self.playground.stopWaterWatch() del self.fsm del self.freezeUpSfx del self.frozenSfxArray del self.coolSfxArray del self.playground
class BaseLocalControls(DirectObject): SlideFactor = 0.75 DiagonalFactor = math.sqrt(2.0) / 2.0 CrouchSpeedFactor = 0.3 FootstepIval = 0.6 FootstepVolumeMod = 1.0 BattleNormalSpeed = 320 / 16.0 BattleRunSpeed = 416 / 16.0 BattleWalkSpeed = 190 / 16.0 SwimGravityMod = 0.5 # Mode MThirdPerson = 0 MFirstPerson = 1 # Scheme SDefault = 0 SSwim = 1 def __init__(self): DirectObject.__init__(self) self.fsm = ClassicFSM('ControlMode', [ State('off', self.enterOff, self.exitOff), State('firstperson', self.enterFirstPerson, self.exitFirstPerson), State('thirdperson', self.enterThirdPerson, self.exitThirdPerson) ], 'off', 'off') self.fsm.enterInitialState() self.controller = None self.staticFriction = 0.8 self.dynamicFriction = 0.3 self.speeds = Vec3(0) self.lastSpeeds = Vec3(0) self.idealFwd = 0 self.idealRev = 0 self.idealRot = 0 self.idealJump = 0 self.fwdSpeed = CIGlobals.ToonForwardSpeed self.revSpeed = CIGlobals.ToonReverseSpeed self.turnSpeed = CIGlobals.ToonRotateSpeed self.controlsEnabled = False self.airborne = False self.crouching = False self.defaultSounds = [ base.loadSfx("phase_14/audio/sfx/footsteps/default1.ogg"), base.loadSfx("phase_14/audio/sfx/footsteps/default2.ogg") ] self.defaultOverride = None #"concrete" self.standingUp = True self.footstepIval = self.FootstepIval self.lastFootstepTime = 0 self.currentSurface = None self.footstepSounds = {} self.currFootstepSound = None self.lastFoot = True self.setCurrentSurface('default') self.currentObjectUsing = None self.lastUseObjectTime = 0.0 self.mode = self.MThirdPerson self.scheme = self.SDefault self.fpsCam = FPSCamera() self.movementTokens = [] self.active = False self.charUpdateTaskName = "controllerUpdateTask-" + str(id(self)) self.useInvalidSound = base.loadSfx("phase_4/audio/sfx/ring_miss.ogg") # Debug stuff self.printFootstepInfo = False #base.localAvatar.accept('i', self.toggleDiagnostic) def getHighestSpeed(self): return self.BattleRunSpeed def cleanup(self): if self.fpsCam: self.fpsCam.cleanup() self.fpsCam = None def toggleDiagnostic(self): self.printFootstepInfo = not self.printFootstepInfo print("Toggled footstep info") def enterOff(self): pass def exitOff(self): pass def setControlScheme(self, scheme): self.scheme = scheme if scheme == self.SSwim: self.controller.setMovementState(MOVEMENTSTATE_SWIMMING) self.controller.setGravity(base.physicsWorld.getGravity()[2] * LocalControls.SwimGravityMod) self.staticFriction = 0.15 self.dynamicFriction = 0.08 self.allowCrouch = False self.allowJump = False else: if self.controller.getMovementState() == MOVEMENTSTATE_SWIMMING: self.controller.setMovementState(MOVEMENTSTATE_GROUND) self.controller.setGravity(base.physicsWorld.getGravity()[2]) self.staticFriction = 0.8 self.dynamicFriction = 0.3 self.allowCrouch = True self.allowJump = True def attachCamera(self): self.fpsCam.attachCamera() def enterFirstPerson(self): self.fpsCam.setup() if self.controlsEnabled: self.fp_enable() self.revSpeed = CIGlobals.ToonForwardSpeed def fp_enable(self, wantMouse=0): if wantMouse: self.fpsCam.enableMouseMovement() else: # At least allow them to engage the mouse. self.fpsCam.acceptEngageKeys() base.localAvatar.resetHeadHpr(True) if base.localAvatar.hasEquippedAttack(): base.localAvatar.showCrosshair() if base.localAvatar.isFirstPerson(): self.fpsCam.getViewModel().show() base.localAvatar.b_setLookMode(base.localAvatar.LMCage) else: base.localAvatar.b_setLookMode(base.localAvatar.LMHead) base.camLens.setMinFov(70.0 / (4. / 3.)) base.localAvatar.enableGagKeys() def exitFirstPerson(self): self.fpsCam.disableMouseMovement() base.localAvatar.hideCrosshair() def enterThirdPerson(self): #base.localAvatar.b_setLookMode(base.localAvatar.LMOff) #base.localAvatar.getGeomNode().show() #self.tp_attachCamera() #base.localAvatar.hideCrosshair() #self.fpsCam.getViewModel().hide() #self.revSpeed = CIGlobals.ToonReverseSpeed\ self.fpsCam.setup() if self.controlsEnabled: self.fp_enable() base.localAvatar.startSmartCamera() self.revSpeed = CIGlobals.ToonForwardSpeed def tp_attachCamera(self): camera.reparentTo(base.localAvatar) base.localAvatar.smartCamera.setCameraPositionByIndex( base.localAvatar.smartCamera.cameraIndex) #camera.setPos(base.localAvatar.smartCamera.getIdealCameraPos()) #camera.lookAt(base.localAvatar.smartCamera.getLookAtPoint()) base.camLens.setMinFov(CIGlobals.DefaultCameraFov / (4. / 3.)) def exitThirdPerson(self): base.localAvatar.stopSmartCamera() def setMode(self, mode): self.mode = mode if mode == self.MFirstPerson: self.fsm.request('firstperson') elif mode == self.MThirdPerson: self.fsm.request('thirdperson') else: self.notify.warning("unknown control mode {0}".format(mode)) return self.watchMovementInputs() def switchMode(self): if self.mode == self.MFirstPerson: self.setMode(self.MThirdPerson) elif self.mode == self.MThirdPerson: self.setMode(self.MFirstPerson) def getCollisionsActive(self): return self.active def setWalkSpeed(self, fwd, jump, rev, rot): self.idealFwd = fwd self.idealJump = jump self.idealRev = rev self.idealRot = rot self.fwdSpeed = fwd self.revSpeed = rev self.turnSpeed = rot def setCollisionsActive(self, flag, andPlaceOnGround=0): if not flag: # There may be times when we need to return the avatar to the # ground so they don't break the laws of physics. Such as # when we disable collisions when moving a player through # a tunnel. if andPlaceOnGround: self.exitControlsWhenGrounded = True else: self.stopControllerUpdate() else: self.startControllerUpdate() def getSpeeds(self): return self.speeds def isMoving(self): return self.speeds.length() != 0 def isCrouching(self): return self.crouching def getFootstepSoundsDir(self): return "phase_14/audio/sfx/footsteps/" def footstepSoundCompare(self, surface, basename): return surface == basename[:len(surface)] def getCorrectedFootstepSound(self, surface): return surface def setCurrentSurface(self, surface): surface = self.getCorrectedFootstepSound(surface) if self.currentSurface == surface: return self.currentSurface = surface if surface == self.getCorrectedFootstepSound( "default") and self.defaultOverride is not None: surface = self.getCorrectedFootstepSound(self.defaultOverride) if not surface in self.footstepSounds: self.footstepSounds[surface] = [] vfs = VirtualFileSystem.getGlobalPtr() for vFile in vfs.scanDirectory(self.getFootstepSoundsDir()): fullPath = vFile.getFilename().getFullpath() if self.footstepSoundCompare( surface, vFile.getFilename().getBasenameWoExtension()): sound = base.loadSfx(fullPath) self.footstepSounds[surface].append(sound) def getCurrentSurface(self): if self.currentSurface == "default" and self.defaultOverride is not None: return self.defaultOverride return self.currentSurface def enableControls(self, wantMouse=0): if self.controlsEnabled: return base.taskMgr.add(self.__handlePlayerControls, "LocalControls.handlePlayerControls") base.taskMgr.add(self.__handleFootsteps, "LocalControls.handleFootsteps", taskChain="fpsIndependentStuff") self.watchMovementInputs() if base.localAvatar.battleControls: base.taskMgr.add(self.__handleUse, "LocalControls.handleUse", taskChain="fpsIndependentStuff") if self.mode == self.MFirstPerson: self.fp_enable(wantMouse) elif self.mode == self.MThirdPerson: self.fp_enable(wantMouse) base.localAvatar.startSmartCamera() self.idealFwd = self.BattleNormalSpeed self.idealRev = self.BattleNormalSpeed self.fwdSpeed = self.idealFwd self.revSpeed = self.idealRev else: self.tp_attachCamera() base.localAvatar.startSmartCamera() self.accept(base.inputStore.NextCameraPosition, base.localAvatar.smartCamera.nextCameraPos, [1]) self.accept(base.inputStore.PreviousCameraPosition, base.localAvatar.smartCamera.nextCameraPos, [0]) self.accept(base.inputStore.LookUp, base.localAvatar.smartCamera.pageUp) self.accept(base.inputStore.LookDown, base.localAvatar.smartCamera.pageDown) self.controlsEnabled = True self.exitControlsWhenGrounded = False def isOnGround(self): if self.controller: return self.controller.isOnGround() return False def __controllerUpdate(self, task): if self.controller: self.controller.update(globalClock.getDt()) self.setCurrentSurface(self.controller.getCurrentMaterial()) return task.cont def startControllerUpdate(self): self.stopControllerUpdate() self.active = True self.controller.placeOnGround() taskMgr.add(self.__controllerUpdate, self.charUpdateTaskName, sort=50) def stopControllerUpdate(self): taskMgr.remove(self.charUpdateTaskName) self.active = False def setupControls(self): self.controller = PhysicsCharacterController( base.bspLoader, base.physicsWorld, render, render, base.localAvatar.getHeight(), base.localAvatar.getHeight() / 2.0, 0.3, 1.0, base.physicsWorld.getGravity()[2], CIGlobals.WallGroup, CIGlobals.FloorGroup | CIGlobals.StreetVisGroup, CIGlobals.EventGroup) self.controller.setDefaultMaterial(self.getDefaultSurface()) self.controller.setMaxSlope(75.0, False) self.controller.setCollideMask(CIGlobals.LocalAvGroup) capsules = [ self.controller.getWalkCapsule(), self.controller.getCrouchCapsule(), self.controller.getEventSphere() ] for cap in capsules: cap.setPythonTag("localAvatar", base.localAvatar) self.controller.setStandUpCallback(self.__handleStandUp) self.controller.setFallCallback(self.__handleLand) self.controller.setEventEnterCallback(self.__handleEventEnter) self.controller.setEventExitCallback(self.__handleEventExit) base.localAvatar.reparentTo(self.controller.getMovementParent()) base.localAvatar.assign(self.controller.getMovementParent()) base.cr.doId2do[base.localAvatar.doId] = base.localAvatar print(taskMgr) self.setControlScheme(self.SDefault) def __handleEventEnter(self, np): print('enter' + np.getName()) messenger.send('enter' + np.getName(), [np]) def __handleEventExit(self, np): print('exit' + np.getName()) messenger.send('exit' + np.getName(), [np]) def releaseMovementInputs(self): for tok in self.movementTokens: tok.release() self.movementTokens = [] def watchMovementInputs(self): self.releaseMovementInputs() if base.localAvatar.battleControls: self.movementTokens.append( inputState.watchWithModifiers('forward', 'w', inputSource=inputState.WASD)) self.movementTokens.append( inputState.watchWithModifiers('reverse', 's', inputSource=inputState.WASD)) self.movementTokens.append( inputState.watchWithModifiers('slideLeft', 'a', inputSource=inputState.WASD)) self.movementTokens.append( inputState.watchWithModifiers('slideRight', 'd', inputSource=inputState.WASD)) self.movementTokens.append( inputState.watchWithModifiers('jump', 'space', inputSource=inputState.WASD)) self.movementTokens.append( inputState.watchWithModifiers('crouch', 'control', inputSource=inputState.WASD)) self.movementTokens.append( inputState.watchWithModifiers('sprint', 'shift', inputSource=inputState.WASD)) self.movementTokens.append( inputState.watchWithModifiers('walk', 'alt', inputSource=inputState.WASD)) self.movementTokens.append( inputState.watchWithModifiers('use', 'e', inputSource=inputState.WASD)) else: self.movementTokens.append( inputState.watchWithModifiers('forward', 'arrow_up', inputSource=inputState.WASD)) self.movementTokens.append( inputState.watchWithModifiers('reverse', 'arrow_down', inputSource=inputState.WASD)) self.movementTokens.append( inputState.watchWithModifiers('turnLeft', 'arrow_left', inputSource=inputState.WASD)) self.movementTokens.append( inputState.watchWithModifiers('turnRight', 'arrow_right', inputSource=inputState.WASD)) self.movementTokens.append( inputState.watchWithModifiers('jump', 'control', inputSource=inputState.WASD)) def disableControls(self, chat=False): if not self.controlsEnabled: return if base.localAvatar.battleControls: self.fpsCam.disableMouseMovement(False, not chat) self.ignore('alt') self.ignore(base.inputStore.NextCameraPosition) self.ignore(base.inputStore.PreviousCameraPosition) if not chat and (base.localAvatar.isThirdPerson() or not base.localAvatar.battleControls): base.localAvatar.stopSmartCamera() inputState.set('forward', False, inputSource=inputState.WASD) inputState.set('reverse', False, inputSource=inputState.WASD) inputState.set('slideLeft', False, inputSource=inputState.WASD) inputState.set('slideRight', False, inputSource=inputState.WASD) inputState.set('jump', False, inputSource=inputState.WASD) inputState.set('crouch', False, inputSource=inputState.WASD) inputState.set('walk', False, inputSource=inputState.WASD) inputState.set('sprint', False, inputSource=inputState.WASD) inputState.set('use', False, inputSource=inputState.WASD) base.taskMgr.remove("LocalControls.handlePlayerControls") base.taskMgr.remove("LocalControls.handleFootsteps") base.taskMgr.remove("LocalControls.handleUse") self.controller.setLinearMovement(Vec3(0)) self.controller.setAngularMovement(0) self.controlsEnabled = False def __handleStandUp(self): self.standingUp = True def __handleLand(self, fallDistance): if self.controlsEnabled: if fallDistance > 8: base.localAvatar.handleJumpHardLand() self.playFootstep(1.5) #if self.mode == LocalControls.MFirstPerson: # self.fpsCam.handleJumpHardLand() else: base.localAvatar.handleJumpLand() if self.exitControlsWhenGrounded: self.stopControllerUpdate() self.exitControlsWhenGrounded = False def getDefaultSurface(self): return "default" def playFootstep(self, volume=1.0): surfSounds = self.footstepSounds[self.getCurrentSurface()] numSounds = len(surfSounds) if numSounds > 0: self.lastFoot = not self.lastFoot mid = int(numSounds / 2) if self.lastFoot: choices = surfSounds[:mid] else: choices = surfSounds[mid:] if self.currFootstepSound: self.currFootstepSound.stop() sound = random.choice(choices) sound.setVolume(volume * self.FootstepVolumeMod) #sound.play() if True: #self.currentSurface != self.getDefaultSurface(): # if it's not the default footstep sound, put the default toon step sound behind it # to sound more like feet running default = self.defaultSounds[int(self.lastFoot)] default.setVolume(volume * self.FootstepVolumeMod) default.play() self.currFootstepSound = sound if self.printFootstepInfo: print("Playing Footstep") print("Num Footstep Tasks: " + str( len( base.taskMgr.getTasksNamed( "LocalControls.handleFootsteps")))) self.lastFootstepTime = globalClock.getFrameTime() def getFootstepIval(self, speed): return CIGlobals.remapVal(speed, self.BattleNormalSpeed, self.BattleRunSpeed, 0.4, 0.3) def getFootstepVolume(self, speed): return min(1, speed / self.BattleNormalSpeed) def __handleFootsteps(self, task): time = globalClock.getFrameTime() speeds = self.speeds.length() if speeds > 0.1 and (self.isOnGround() or self.scheme == self.SSwim): self.footstepIval = self.getFootstepIval(speeds) if self.scheme == self.SSwim: self.footstepIval *= 6.0 if time - self.lastFootstepTime >= self.footstepIval: self.playFootstep(self.getFootstepVolume(speeds)) return task.cont def __handleUse(self, task): #if self.mode == LocalControls.MThirdPerson: # return task.cont time = globalClock.getFrameTime() use = inputState.isSet('use') if use: # see if there is anything for us to use. distance = 7.5 camQuat = base.camera.getQuat(render) camFwd = camQuat.xform(Vec3.forward()) camPos = base.camera.getPos(render) if self.mode == self.MFirstPerson: start = camPos else: # Move the line out to their character. # This prevents the player from using things that # are behind their character, but in front of # the camera. laPos = base.localAvatar.getPos(render) camToPlyr = (camPos.getXy() - laPos.getXy()).length() start = camPos + (camFwd * camToPlyr) stop = start + (camFwd * distance) hit = PhysicsUtils.rayTestClosestNotMe(base.localAvatar, start, stop, CIGlobals.UseableGroup) somethingToUse = False if hit is not None: node = hit.getNode() if node.hasPythonTag("useableObject"): somethingToUse = True obj = node.getPythonTag("useableObject") if obj.canUse(): if self.currentObjectUsing != obj: if self.currentObjectUsing is not None: self.currentObjectUsing.stopUse() obj.startUse() self.lastUseObjectTime = time elif time - self.lastUseObjectTime >= obj.useIval: obj.use() self.lastUseObjectTime = time self.currentObjectUsing = obj if not somethingToUse and not self.lastUse: self.useInvalidSound.play() else: if self.currentObjectUsing is not None: self.currentObjectUsing.stopUse() self.currentObjectUsing = None self.lastUse = use return task.cont def __handlePlayerControls(self, task): dt = globalClock.getDt() time = globalClock.getFrameTime() forward = inputState.isSet('forward') reverse = inputState.isSet('reverse') slideLeft = inputState.isSet('slideLeft') slideRight = inputState.isSet('slideRight') turnLeft = inputState.isSet('turnLeft') turnRight = inputState.isSet('turnRight') jump = inputState.isSet('jump') crouch = inputState.isSet('crouch') sprint = inputState.isSet('sprint') walk = inputState.isSet('walk') # Determine goal speeds speed = Vec3(0) if forward: speed.setY(self.fwdSpeed) elif reverse: speed.setY(-self.revSpeed) else: speed.setY(0) if reverse and slideLeft: speed.setX(-self.revSpeed * self.SlideFactor) elif reverse and slideRight: speed.setX(self.revSpeed * self.SlideFactor) elif slideLeft: speed.setX(-self.fwdSpeed * self.SlideFactor) elif slideRight: speed.setX(self.fwdSpeed * self.SlideFactor) else: speed.setX(0) if speed.getX() != 0 and speed.getY() != 0: speed.setX(speed.getX() * self.DiagonalFactor) speed.setY(speed.getY() * self.DiagonalFactor) if turnLeft: speed.setZ(self.turnSpeed) elif turnRight: speed.setZ(-self.turnSpeed) else: speed.setZ(0) self.speeds = Vec3(speed) if base.localAvatar.battleControls: # Apply smoothed out movement in battle controls. sFriction = 1 - math.pow(1 - self.staticFriction, dt * 30.0) dFriction = 1 - math.pow(1 - self.dynamicFriction, dt * 30.0) # Apply friction to the goal speeds if abs(self.speeds.getX()) < abs(self.lastSpeeds.getX()): self.lastSpeeds.setX(self.speeds.getX() * dFriction + self.lastSpeeds.getX() * (1 - dFriction)) else: self.lastSpeeds.setX(self.speeds.getX() * sFriction + self.lastSpeeds.getX() * (1 - sFriction)) if abs(self.speeds.getY()) < abs(self.lastSpeeds.getY()): self.lastSpeeds.setY(self.speeds.getY() * dFriction + self.lastSpeeds.getY() * (1 - dFriction)) else: self.lastSpeeds.setY(self.speeds.getY() * sFriction + self.lastSpeeds.getY() * (1 - sFriction)) if abs(self.speeds.getZ()) < abs(self.lastSpeeds.getZ()): self.lastSpeeds.setZ(self.speeds.getZ() * dFriction + self.lastSpeeds.getZ() * (1 - dFriction)) else: self.lastSpeeds.setZ(self.speeds.getZ() * sFriction + self.lastSpeeds.getZ() * (1 - sFriction)) else: self.lastSpeeds = self.speeds self.speeds = Vec3(self.lastSpeeds) if abs(self.speeds.getX()) < 0.1: self.speeds.setX(0) if abs(self.speeds.getY()) < 0.1: self.speeds.setY(0) if abs(self.speeds.getZ()) < 0.1: self.speeds.setZ(0) linearSpeed = Vec3(self.speeds[0], self.speeds[1], 0.0) if self.scheme == self.SSwim and self.mode == self.MFirstPerson: # When swimming in first person, move in the direction we are looking, like flying. linearSpeed = self.fpsCam.camRoot.getQuat(render).xform( linearSpeed) else: linearSpeed = base.localAvatar.getQuat(render).xform(linearSpeed) self.controller.setLinearMovement(linearSpeed) self.controller.setAngularMovement(self.speeds.getZ()) onGround = self.isOnGround() if jump and onGround and not self.airborne and ( self.allowJump and not base.localAvatar.isDead()): self.controller.startJump(3.0) self.playFootstep(1.5) self.airborne = True elif onGround and self.controller.getMovementState( ) == MOVEMENTSTATE_GROUND: # We landed self.airborne = False if walk: fctr = 0.6 self.fwdSpeed = self.BattleWalkSpeed self.revSpeed = self.BattleWalkSpeed elif sprint: self.fwdSpeed = self.BattleRunSpeed self.revSpeed = self.BattleRunSpeed elif not self.crouching: self.fwdSpeed = self.idealFwd self.revSpeed = self.idealRev if crouch and not self.crouching and self.allowCrouch: fctr = self.CrouchSpeedFactor self.fwdSpeed = self.idealFwd * fctr self.revSpeed = self.idealRev * fctr self.controller.startCrouch() self.crouching = True self.standingUp = False elif not crouch and self.crouching: self.controller.stopCrouch() if self.standingUp: self.fwdSpeed = self.idealFwd self.revSpeed = self.idealRev self.crouching = False moveBits = 0 if self.isMoving(): moveBits |= CIGlobals.MB_Moving if self.crouching: moveBits |= CIGlobals.MB_Crouching if walk: moveBits |= CIGlobals.MB_Walking if moveBits != base.localAvatar.moveBits: base.localAvatar.b_setMoveBits(moveBits) return task.cont
class RemoteToonBattleAvatar(RemoteAvatar): notify = directNotify.newCategory('RemoteToonBattleAvatar') def __init__(self, mg, cr, avId, gunName = 'pistol'): RemoteAvatar.__init__(self, mg, cr, avId) self.track = None self.gunName = gunName self.fsm = ClassicFSM('RemoteToonBattleAvatar', [State('off', self.enterOff, self.exitOff), State('shoot', self.enterShoot, self.exitShoot), State('die', self.enterDie, self.exitDie), State('dead', self.enterDead, self.exitDead)], 'off', 'off') self.fsm.enterInitialState() self.soundGrunt = None self.retrieveAvatar() return def setGunName(self, gunName): self.gunName = gunName self.avatar.attachGun(gunName) def getGunName(self): return self.gunName def retrieveAvatar(self): RemoteAvatar.retrieveAvatar(self) if self.avatar: self.avatar.attachGun(self.gunName) self.soundGrunt = base.loadSfx('phase_4/audio/sfx/target_impact_grunt1.mp3') def enterOff(self): pass def exitOff(self): pass def grunt(self): base.playSfx(self.soundGrunt, node=self.avatar) def enterDead(self): if self.avatar: self.avatar.stash() def exitDead(self): if self.avatar: self.avatar.unstash() self.avatar.clearColorScale() self.avatar.getGeomNode().clearColorScale() self.avatar.clearTransparency() self.avatar.getGeomNode().clearTransparency() self.avatar.getNameTag().clearColorScale() def enterDie(self, ts): if self.avatar: dieSound = base.audio3d.loadSfx(self.avatar.getToonAnimalNoise('exclaim')) base.audio3d.attachSoundToObject(dieSound, self.avatar) self.avatar.setTransparency(1) self.avatar.getGeomNode().setTransparency(1) self.track = Sequence(Func(dieSound.play), Parallel(LerpColorScaleInterval(self.avatar.getGeomNode(), colorScale=VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1), duration=0.5), LerpColorScaleInterval(self.avatar.getNameTag(), colorScale=VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1), duration=0.5), ActorInterval(self.avatar, 'fallb')), Func(self.fsm.request, 'dead')) self.track.start(ts) del dieSound def exitDie(self): self.resetTrack() def resetTrack(self): if self.track: self.track.pause() self.track = None return def run(self): if self.avatar: if self.track and self.track.isPlaying(): self.avatar.loop('run', partName='legs') else: self.avatar.loop('run') def stand(self): if self.avatar: if self.track and self.track.isPlaying(): self.avatar.loop('neutral', partName='legs') else: self.avatar.loop('neutral') def jump(self): if self.avatar: if self.track and self.track.isPlaying(): self.avatar.loop('jump', partName='legs') else: self.avatar.loop('jump') def enterShoot(self, ts): if self.avatar: def createBullet(): if self.gunName == 'pistol': Bullet(self.mg, self.avatar.gun.find('**/joint_nozzle'), 0, self.gunName) elif self.gunName == 'shotgun': b1 = Bullet(self.mg, self.avatar.gun.find('**/joint_nozzle'), 0, self.gunName) b2 = Bullet(self.mg, self.avatar.gun.find('**/joint_nozzle'), 0, self.gunName) def changeToLegAnim(): self.avatar.loop(self.avatar.getCurrentAnim(partName='legs')) if self.gunName == 'pistol': gunSound = base.audio3d.loadSfx('phase_4/audio/sfx/pistol_shoot.wav') elif self.gunName == 'shotgun': gunSound = base.audio3d.loadSfx('phase_4/audio/sfx/shotgun_shoot.wav') base.audio3d.attachSoundToObject(gunSound, self.avatar) self.track = Sequence(Func(createBullet), Func(gunSound.play), ActorInterval(self.avatar, 'squirt', partName='torso', startFrame=48, endFrame=58), ActorInterval(self.avatar, 'squirt', partName='torso', startFrame=107, endFrame=126, playRate=3), Func(changeToLegAnim)) self.track.start(ts) del gunSound self.mg.makeSmokeEffect(self.avatar.gun.find('**/joint_nozzle').getPos(render)) def exitShoot(self): self.resetTrack() def cleanup(self): if self.avatar: self.avatar.detachGun() self.soundGrunt = None if self.track: self.track.pause() del self.track RemoteAvatar.cleanup(self) return
class ShtickerBook(StateData): def __init__(self, parentFSM, doneEvent): self.parentFSM = parentFSM StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('ShtickerBook', [ State('off', self.enterOff, self.exitOff), State('optionPage', self.enterOptionPage, self.exitOptionPage, ['districtPage', 'off']), State('districtPage', self.enterDistrictPage, self.exitDistrictPage, ['optionPage', 'questPage', 'off']), State('questPage', self.enterQuestPage, self.exitQuestPage, ['inventoryPage', 'districtPage', 'off']), State('inventoryPage', self.enterInventoryPage, self.exitInventoryPage, ['mapPage', 'questPage', 'off']), State('mapPage', self.enterMapPage, self.exitMapPage, ['inventoryPage', 'off']), State('releaseNotesPage', self.enterReleaseNotesPage, self.exitReleaseNotesPage, ['mapPage', 'off']), State('adminPage', self.enterAdminPage, self.exitAdminPage, ['mapPage', 'namePage', 'off']), State('namePage', self.enterNamePage, self.exitNamePage, ['adminPage', 'off']) ], 'off', 'off') if base.localAvatar.getAdminToken() > -1: self.fsm.getStateNamed('mapPage').addTransition('adminPage') self.fsm.enterInitialState() self.entered = 0 self.parentFSM.getStateNamed('shtickerBook').addChild(self.fsm) def enterOff(self): pass def exitOff(self): pass def load(self): StateData.load(self) self.book_contents = loader.loadModel( "phase_3.5/models/gui/stickerbook_gui.bam") self.book_texture = self.book_contents.find('**/big_book') self.book_open = loader.loadSfx( "phase_3.5/audio/sfx/GUI_stickerbook_open.ogg") self.book_close = loader.loadSfx( "phase_3.5/audio/sfx/GUI_stickerbook_delete.ogg") self.book_turn = loader.loadSfx( "phase_3.5/audio/sfx/GUI_stickerbook_turn.ogg") def unload(self): self.book_texture.removeNode() del self.book_texture self.book_contents.removeNode() del self.book_contents loader.unloadSfx(self.book_open) del self.book_open loader.unloadSfx(self.book_close) del self.book_close loader.unloadSfx(self.book_turn) del self.book_turn del self.fsm del self.parentFSM del self.entered StateData.unload(self) def enter(self, page): if self.entered: return self.entered = 1 StateData.enter(self) render.hide() base.setBackgroundColor(0.05, 0.15, 0.4) self.book_img = OnscreenImage(image=self.book_texture, scale=(2, 1, 1.5)) self.book_open.play() if base.localAvatar.getAdminToken() > -1: self.fsm.request('adminPage') else: self.fsm.request(page) def exit(self): if not self.entered: return self.entered = 0 base.setBackgroundColor(CIGlobals.DefaultBackgroundColor) render.show() self.book_img.destroy() del self.book_img self.book_close.play() self.fsm.request('off') StateData.exit(self) def enterDistrictPage(self): self.createPageButtons('optionPage', 'questPage') self.setTitle("Districts") currDistrictName = base.cr.myDistrict.getDistrictName() if not currDistrictName.isalpha(): currDistrictName = currDistrictName[:-1] self.infoLbl = OnscreenText( text='Each District is a copy of the Cog Invasion world.\n' '\n\nYou are currently in the "%s" District' % currDistrictName, pos=(0.05, 0.3), align=TextNode.ALeft, wordwrap=12) self.populationLbl = OnscreenText(text="Population: %d" % base.cr.myDistrict.getPopulation(), pos=(0.44, -0.3), align=TextNode.ACenter) textRolloverColor = Vec4(1, 1, 0, 1) textDownColor = Vec4(0.5, 0.9, 1, 1) textDisabledColor = Vec4(0.4, 0.8, 0.4, 1) self.shardButtons = [] for shard in base.cr.activeDistricts.values(): shardName = shard.getDistrictName() shardId = shard.doId btn = DirectButton(relief=None, text=shardName, text_scale=0.07, text_align=TextNode.ALeft, text1_bg=textDownColor, text2_bg=textRolloverColor, text3_fg=textDisabledColor, textMayChange=0, command=self.__handleShardButton, extraArgs=[shardId], text_pos=(0, 0, 0.0)) if shardId == base.localAvatar.parentId: btn['state'] = DGG.DISABLED else: btn['state'] = DGG.NORMAL self.shardButtons.append(btn) gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam') listXorigin = -0.02 listFrameSizeX = 0.625 listZorigin = -0.96 listFrameSizeZ = 1.04 arrowButtonScale = 1.3 itemFrameXorigin = -0.237 itemFrameZorigin = 0.365 buttonXstart = itemFrameXorigin + 0.293 self.districtList = DirectScrolledList( relief=None, pos=(-0.54, 0, 0.08), incButton_image=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), incButton_relief=None, incButton_scale=(arrowButtonScale, arrowButtonScale, -arrowButtonScale), incButton_pos=(buttonXstart, 0, itemFrameZorigin - 0.999), incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), decButton_relief=None, decButton_scale=(arrowButtonScale, arrowButtonScale, arrowButtonScale), decButton_pos=(buttonXstart, 0, itemFrameZorigin + 0.125), decButton_image3_color=Vec4(1, 1, 1, 0.2), itemFrame_pos=(itemFrameXorigin, 0, itemFrameZorigin), itemFrame_scale=1.0, itemFrame_relief=DGG.SUNKEN, itemFrame_frameSize=(listXorigin, listXorigin + listFrameSizeX, listZorigin, listZorigin + listFrameSizeZ), itemFrame_frameColor=(0.85, 0.95, 1, 1), itemFrame_borderWidth=(0.01, 0.01), numItemsVisible=15, forceHeight=0.075, items=self.shardButtons) base.taskMgr.add(self.__updateDistrictPopTask, "SB.updateDistrictPopTask") def __handleShardButton(self, shardId): self.finished("switchShard", shardId) def __updateDistrictPopTask(self, task): population = base.cr.myDistrict.getPopulation() self.populationLbl.setText('Population: %d' % population) task.delayTime = 5.0 return task.again def exitDistrictPage(self): base.taskMgr.remove('SB.updateDistrictPopTask') for btn in self.shardButtons: btn.destroy() del self.shardButtons self.districtList.destroy() del self.districtList self.infoLbl.destroy() del self.infoLbl self.populationLbl.destroy() del self.populationLbl self.deletePageButtons(True, True) self.clearTitle() def enterNamePage(self): self.namePageStateData = NamePage(self, self.fsm) self.namePageStateData.load() self.namePageStateData.enter() def exitNamePage(self): self.namePageStateData.exit() self.namePageStateData.unload() del self.namePageStateData def enterQuestPage(self): self.createPageButtons('districtPage', 'inventoryPage') self.setTitle("Quests") """ self.notes = base.localAvatar.questManager.makeQuestNotes() for note in self.notes: note.show() """ self.posters = [] for quest in base.localAvatar.questManager.getQuests(): poster = QuestPoster(quest) poster.update() self.posters.append(poster) self.infoText = OnscreenText( text= "Return completed Quests to an HQ Officer at any Toon HQ building.", pos=(0, -0.6), scale=0.045) def exitQuestPage(self): self.infoText.destroy() del self.infoText for poster in self.posters: poster.destroy() """ for note in self.notes: note.destroy() """ self.deletePageButtons(True, True) self.clearTitle() def enterInventoryPage(self): self.createPageButtons('questPage', 'mapPage') self.setTitle('Gags') self.gui = BackpackGUI() self.gui.createGUI() def exitInventoryPage(self): self.gui.deleteGUI() del self.gui self.deletePageButtons(True, True) self.clearTitle() def enterMapPage(self): if base.localAvatar.getAdminToken() > -1: self.createPageButtons('inventoryPage', 'adminPage') else: self.createPageButtons('inventoryPage', None) self.setTitle("") themap = loader.loadModel('phase_3.5/models/gui/toontown_map.bam') self.frame = DirectFrame(parent=aspect2d, relief=None, image=themap, image_scale=(1.8, 1, 1.35), scale=0.97, pos=(0, 0, 0.0775)) cloudpos = [[(-0.61, 0, 0.18), (0.55, 0.25, 0.37), (180, 0, 0)], [(-0.54, 0, 0.34), (0.76, 0.4, 0.55), (180, 0, 0)], [(-0.55, 0, -0.09), (0.72, 0.4, 0.55), (0, 0, 0)], [(-0.67, 0, -0.51), (0.5, 0.29, 0.38), (180, 0, 0)], [(-0.67, 0, 0.51), (0.50, 0.29, 0.38), (0, 0, 0)], [(0.67, 0, 0.51), (0.5, 0.29, 0.38), (0, 0, 0)], [(0.35, 0, -0.46), (0.63, 0.35, 0.45), (0, 0, 0)], [(0.18, 0, -0.45), (0.52, 0.27, 0.32), (0, 0, 0)], [(0.67, 0, -0.44), (0.63, 0.35, 0.48), (180, 0, 0)]] hoodclouds = [ #[(0.02, 0, -0.17), (0.63, 0.35, 0.48), (180, 0, 0), CIGlobals.ToontownCentral], [(0.63, 0, -0.13), (0.63, 0.35, 0.40), (0, 0, 0), CIGlobals.DonaldsDock], [(0.51, 0, 0.25), (0.57, 0.35, 0.40), (0, 0, 0), CIGlobals.TheBrrrgh], [(0.03, 0, 0.19), (0.63, 0.35, 0.40), (180, 0, 0), CIGlobals.MinniesMelodyland], [(-0.08, 0, 0.46), (0.54, 0.35, 0.40), (0, 0, 0), CIGlobals.DonaldsDreamland], [(-0.28, 0, -0.49), (0.60, 0.35, 0.45), (0, 0, 0), CIGlobals.DaisyGardens] ] self.clouds = [] self.labels = [] for pos, scale, hpr in cloudpos: cloud = loader.loadModel('phase_3.5/models/gui/cloud.bam') cloud.reparentTo(self.frame) cloud.setPos(pos) cloud.setScale(scale) cloud.setHpr(hpr) self.clouds.append(cloud) for pos, scale, hpr, hood in hoodclouds: if not base.localAvatar.hasDiscoveredHood( ZoneUtil.getZoneId(hood)): cloud = loader.loadModel('phase_3.5/models/gui/cloud.bam') cloud.reparentTo(self.frame) cloud.setPos(pos) cloud.setScale(scale) cloud.setHpr(hpr) self.clouds.append(cloud) labeldata = [[(0, 0, -0.2), CIGlobals.ToontownCentral], [(0.65, 0, -0.125), CIGlobals.DonaldsDock], [(0.07, 0, 0.18), CIGlobals.MinniesMelodyland], [(-0.1, 0, 0.45), CIGlobals.DonaldsDreamland], [(0.5, 0, 0.25), CIGlobals.TheBrrrgh], [(-0.37, 0, -0.525), CIGlobals.DaisyGardens]] for pos, name in labeldata: if base.localAvatar.hasDiscoveredHood(ZoneUtil.getZoneId(name)): text = name if base.localAvatar.hasTeleportAccess( ZoneUtil.getZoneId(name)): text = 'Go To\n' + text label = DirectButton(parent=self.frame, relief=None, pos=pos, pad=(0.2, 0.16), text=('', text, text, ''), text_bg=Vec4(1, 1, 1, 0.4), text_scale=0.055, text_wordwrap=8, rolloverSound=None, clickSound=None, pressEffect=0, sortOrder=1, text_font=CIGlobals.getToonFont()) if base.localAvatar.hasTeleportAccess( ZoneUtil.getZoneId(name)): label['command'] = self.finished label['extraArgs'] = [ZoneUtil.getZoneId(name)] label.resetFrameSize() self.labels.append(label) currHoodName = base.cr.playGame.hood.id currLocation = '' if base.localAvatar.zoneId == CIGlobals.MinigameAreaId or base.localAvatar.getMyBattle( ) is not None: currLocation = '' elif ZoneUtil.getWhereName(base.localAvatar.zoneId) == 'playground': currLocation = 'Playground' elif ZoneUtil.getWhereName( base.localAvatar.zoneId) in ['street', 'interior']: currLocation = CIGlobals.BranchZone2StreetName[ ZoneUtil.getBranchZone(base.localAvatar.zoneId)] self.infoLabel = DirectLabel(relief=None, text='You are in: {0}\n{1}'.format( currHoodName, currLocation), scale=0.06, pos=(-0.4, 0, -0.74), parent=self.frame, text_align=TextNode.ACenter) if currHoodName in [CIGlobals.MinigameArea, CIGlobals.BattleTTC]: currHoodName = base.cr.playGame.lastHood btpText = "Back to Playground" btpEA = [ZoneUtil.getZoneId(currHoodName)] self.BTPButton = DirectButton(relief=None, text=btpText, geom=CIGlobals.getDefaultBtnGeom(), text_pos=(0, -0.018), geom_scale=(1.3, 1.11, 1.11), text_scale=0.06, parent=self.frame, text_font=CIGlobals.getToonFont(), pos=(0.25, 0, -0.75), command=self.finished, extraArgs=btpEA, scale=0.7) if base.localAvatar.zoneId != CIGlobals.MinigameAreaId: self.MGAButton = DirectButton(relief=None, text="Minigame Area", geom=CIGlobals.getDefaultBtnGeom(), text_pos=(0, -0.018), geom_scale=(1, 1.11, 1.11), text_scale=0.06, parent=self.frame, text_font=CIGlobals.getToonFont(), pos=(0.625, 0, -0.75), command=self.finished, extraArgs=[CIGlobals.MinigameAreaId], scale=0.7) def exitMapPage(self): for label in self.labels: label.destroy() del self.labels for cloud in self.clouds: cloud.removeNode() del self.clouds self.frame.destroy() del self.frame self.infoLabel.destroy() del self.infoLabel self.BTPButton.destroy() del self.BTPButton if hasattr(self, 'MGAButton'): self.MGAButton.destroy() del self.MGAButton if base.localAvatar.getAdminToken() > -1: self.deletePageButtons(True, True) else: self.deletePageButtons(True, False) self.clearTitle() def enterZonePage(self): self.createPageButtons('inventoryPage', 'releaseNotesPage') self.setTitle("Places") #self.home_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), # qt_btn.find('**/QuitBtn_DN'), # qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.055, text=CIGlobals.Estate, command=self.setHood, extraArgs=[10], pos=(-0.45, 0.55, 0.55)) self.ttc_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.045, text=CIGlobals.ToontownCentral, command=self.finished, extraArgs=[CIGlobals.ToontownCentralId], pos=(-0.45, 0.15, 0.5), text_pos=(0, -0.01)) self.tbr_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.055, text=CIGlobals.TheBrrrgh, command=self.finished, extraArgs=[CIGlobals.TheBrrrghId], pos=(-0.45, 0.15, 0.38), text_pos=(0, -0.01)) self.ddl_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.044, text=CIGlobals.DonaldsDreamland, command=self.finished, extraArgs=[CIGlobals.DonaldsDreamlandId], pos=(-0.45, 0.15, 0.26), text_pos=(0, -0.01)) self.mml_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.0425, text=CIGlobals.MinniesMelodyland, command=self.finished, extraArgs=[CIGlobals.MinniesMelodylandId], pos=(-0.45, 0.35, 0.14), text_pos=(0, -0.01)) self.dg_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.045, text=CIGlobals.DaisyGardens, command=self.finished, extraArgs=[CIGlobals.DaisyGardensId], pos=(-0.45, 0.35, 0.02), text_pos=(0, -0.01)) self.dd_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.045, text=CIGlobals.DonaldsDock, command=self.finished, extraArgs=[CIGlobals.DonaldsDockId], pos=(-0.45, 0.35, -0.1), text_pos=(0, -0.01)) self.minigame_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.055, text=CIGlobals.MinigameArea, command=self.finished, extraArgs=[CIGlobals.MinigameAreaId], pos=(-0.45, 0.35, -0.34), text_pos=(0, -0.01)) #self.populationLbl = OnscreenText(text = "", pos = (0.45, 0.1), align = TextNode.ACenter) #self.popRecordLbl = OnscreenText(text = "", pos = (0.45, -0.1), align = TextNode.ACenter, scale = 0.05) #taskMgr.add(self.__updateGamePopulation, "ShtickerBook-updateGamePopulation") def __updateGamePopulation(self, task): population = 0 for district in base.cr.activeDistricts.values(): population += district.getPopulation() self.populationLbl.setText("Game Population:\n" + str(population)) recordPopulation = base.cr.myDistrict.getPopRecord() self.popRecordLbl.setText("Record Population:\n" + str(recordPopulation)) task.delayTime = 5.0 return task.again def exitZonePage(self): #taskMgr.remove("ShtickerBook-updateGamePopulation") #self.popRecordLbl.destroy() #del self.popRecordLbl #self.populationLbl.destroy() #del self.populationLbl self.dd_btn.destroy() del self.dd_btn self.ddl_btn.destroy() del self.ddl_btn self.ttc_btn.destroy() del self.ttc_btn self.tbr_btn.destroy() del self.tbr_btn self.minigame_btn.destroy() del self.minigame_btn self.mml_btn.destroy() del self.mml_btn self.dg_btn.destroy() del self.dg_btn self.deletePageButtons(True, True) self.clearTitle() def createPageButtons(self, back, fwd): if back: self.btn_prev = DirectButton( geom=(self.book_contents.find('**/arrow_button'), self.book_contents.find('**/arrow_down'), self.book_contents.find('**/arrow_rollover')), relief=None, pos=(-0.838, 0, -0.661), scale=(-0.1, 0.1, 0.1), command=self.pageDone, extraArgs=[back]) self.acceptOnce('arrow_left-up', self.pageDone, [back]) if fwd: self.btn_next = DirectButton( geom=(self.book_contents.find('**/arrow_button'), self.book_contents.find('**/arrow_down'), self.book_contents.find('**/arrow_rollover')), relief=None, pos=(0.838, 0, -0.661), scale=(0.1, 0.1, 0.1), command=self.pageDone, extraArgs=[fwd]) self.acceptOnce('arrow_right-up', self.pageDone, [fwd]) def deletePageButtons(self, back, fwd): if back: self.ignore('arrow_left-up') self.btn_prev.destroy() del self.btn_prev if fwd: self.ignore('arrow_right-up') self.btn_next.destroy() del self.btn_next def setTitle(self, title): self.page_title = OnscreenText(text=title, pos=(0, 0.62, 0), scale=0.12) def clearTitle(self): self.page_title.destroy() del self.page_title def enterReleaseNotesPage(self): if base.localAvatar.getAdminToken() > -1: self.createPageButtons('mapPage', 'adminPage') else: self.createPageButtons('mapPage', None) self.setTitle("Release Notes") self.frame = DirectScrolledFrame(canvasSize=(-1, 1, -3.5, 1), frameSize=(-1, 1, -0.6, 0.6)) self.frame.setPos(0, 0, 0) self.frame.setScale(0.8) self.release_notes = DirectLabel(text=open("release_notes.txt", "r").read(), text_align=TextNode.ALeft, pos=(-0.955, 0, 0.93), relief=None, text_fg=(0, 0, 0, 1), text_wordwrap=37.0, text_scale=0.05, parent=self.frame.getCanvas()) def exitReleaseNotesPage(self): self.frame.destroy() del self.frame self.release_notes.destroy() del self.release_notes self.clearTitle() if base.localAvatar.getAdminToken() > -1: self.deletePageButtons(True, True) else: self.deletePageButtons(True, False) def enterAdminPage(self): self.adminPageStateData = AdminPage(self, self.fsm) self.adminPageStateData.load() self.adminPageStateData.enter() def exitAdminPage(self): self.adminPageStateData.exit() self.adminPageStateData.unload() del self.adminPageStateData def pageDone(self, nextPage): base.cr.playGame.getPlace().lastBookPage = nextPage if hasattr(self, 'fsm'): self.fsm.request(nextPage) self.book_turn.play() def enterOptionPage(self): self.optionPageStateData = OptionPage(self, self.fsm) #self.acceptOnce(self.optionPageStateData.doneEvent, self.pageDone) self.optionPageStateData.load() self.optionPageStateData.enter() def exitOptionPage(self): #self.ignore(self.optionPageStateData.doneEvent) self.optionPageStateData.exit() self.optionPageStateData.unload() del self.optionPageStateData def prevPage(self, currentPage): self.clearCurrentPage() if self.currentPage == 2: self.optionPage() elif self.currentPage == 3: self.zonePage() elif self.currentPage == 4: self.releaseNotesPage() def nextPage(self, currentPage): self.clearCurrentPage() if self.currentPage == 1: self.zonePage() elif self.currentPage == 2: self.releaseNotesPage() elif self.currentPage == 3: self.adminPage() def clearCurrentPage(self): self.book_turn.play() for m in base.bookpgnode.getChildren(): m.removeNode() def finished(self, zone, shardId=None): if base.localAvatar.getHealth() < 1 and type(zone) == type(1): return doneStatus = {} if zone in [ CIGlobals.ToontownCentralId, CIGlobals.MinigameAreaId, CIGlobals.TheBrrrghId, CIGlobals.DonaldsDreamlandId, CIGlobals.MinniesMelodylandId, CIGlobals.DaisyGardensId, CIGlobals.DonaldsDockId ]: doneStatus["mode"] = 'teleport' doneStatus["zoneId"] = zone doneStatus["hoodId"] = ZoneUtil.getHoodId(zone) doneStatus["where"] = ZoneUtil.getWhereName(zone) doneStatus["how"] = 'teleportIn' doneStatus["avId"] = base.localAvatar.doId doneStatus["shardId"] = None doneStatus["loader"] = ZoneUtil.getLoaderName(zone) else: doneStatus["mode"] = zone if zone == "switchShard": doneStatus["shardId"] = shardId self.doneStatus = doneStatus messenger.send(self.doneEvent) def closeBook(self): self.book_close.play() base.bookpgnode.removeNode() base.booknode.removeNode()
class Char(Avatar.Avatar): def __init__(self): try: self.Char_initialized return except: self.Char_initialized = 1 Avatar.Avatar.__init__(self) self.avatarType = CIGlobals.CChar self.avatarName = None self.currentAnim = None self.charType = '' self.eyes = loader.loadTexture('phase_3/maps/eyes1.jpg', 'phase_3/maps/eyes1_a.rgb') self.closedEyes = loader.loadTexture('phase_3/maps/mickey_eyes_closed.jpg', 'phase_3/maps/mickey_eyes_closed_a.rgb') self.animFSM = ClassicFSM('Char', [State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('walk', self.enterWalk, self.exitWalk), State('run', self.enterRun, self.exitRun)], 'off', 'off') animStateList = self.animFSM.getStates() self.animFSM.enterInitialState() Avatar.Avatar.initializeBodyCollisions(self, self.avatarType, 3.5, 1) return def stopAnimations(self): if hasattr(self, 'animFSM'): if not self.animFSM.isInternalStateInFlux(): self.animFSM.request('off') else: notify.warning('animFSM in flux, state=%s, not requesting off' % self.animFSM.getCurrentState().getName()) else: notify.warning('animFSM has been deleted') def disable(self): self.stopBlink() self.stopAnimations() Avatar.Avatar.disable(self) def delete(self): try: self.Char_deleted except: self.Char_deleted = 1 del self.animFSM Avatar.Avatar.delete(self) def setChat(self, chatString): if self.charType == CIGlobals.Mickey: self.dial = base.audio3d.loadSfx('phase_3/audio/dial/mickey.wav') elif self.charType == CIGlobals.Minnie: self.dial = base.audio3d.loadSfx('phase_3/audio/dial/minnie.wav') elif self.charType == CIGlobals.Goofy: self.dial = base.audio3d.loadSfx('phase_6/audio/dial/goofy.wav') base.audio3d.attachSoundToObject(self.dial, self) self.dial.play() Avatar.Avatar.setChat(self, chatString) def setName(self, nameString, charName = None): self.avatarName = nameString Avatar.Avatar.setName(self, nameString, avatarType=self.avatarType, charName=charName) def generateChar(self, charType): self.charType = charType if charType == CIGlobals.Mickey or charType == CIGlobals.Minnie: self.loadModel('phase_3/models/char/' + charType.lower() + '-' + str(CIGlobals.ModelDetail(self.avatarType)) + '.bam') self.loadAnims({'neutral': 'phase_3/models/char/' + charType.lower() + '-wait.bam', 'walk': 'phase_3/models/char/' + charType.lower() + '-walk.bam', 'run': 'phase_3/models/char/' + charType.lower() + '-run.bam', 'left-start': 'phase_3.5/models/char/' + charType.lower() + '-left-start.bam', 'left': 'phase_3.5/models/char/' + charType.lower() + '-left.bam', 'right-start': 'phase_3.5/models/char/' + charType.lower() + '-right-start.bam', 'right': 'phase_3.5/models/char/' + charType.lower() + '-right.bam'}) if charType == CIGlobals.Mickey: self.mickeyEye = self.controlJoint(None, 'modelRoot', 'joint_pupilR') self.mickeyEye.setY(0.025) for bundle in self.getPartBundleDict().values(): bundle = bundle['modelRoot'].getBundle() earNull = bundle.findChild('sphere3') if not earNull: earNull = bundle.findChild('*sphere3') earNull.clearNetTransforms() for bundle in self.getPartBundleDict().values(): charNodepath = bundle['modelRoot'].partBundleNP bundle = bundle['modelRoot'].getBundle() earNull = bundle.findChild('sphere3') if not earNull: earNull = bundle.findChild('*sphere3') ears = charNodepath.find('**/sphere3') if ears.isEmpty(): ears = charNodepath.find('**/*sphere3') ears.clearEffect(CharacterJointEffect.getClassType()) earRoot = charNodepath.attachNewNode('earRoot') earPitch = earRoot.attachNewNode('earPitch') earPitch.setP(40.0) ears.reparentTo(earPitch) earNull.addNetTransform(earRoot.node()) ears.clearMat() ears.node().setPreserveTransform(ModelNode.PTNone) ears.setP(-40.0) ears.flattenMedium() ears.setBillboardAxis() self.startBlink() elif charType == CIGlobals.Pluto: self.loadModel('phase_6/models/char/pluto-1000.bam') self.loadAnims({'walk': 'phase_6/models/char/pluto-walk.bam', 'neutral': 'phase_6/models/char/pluto-neutral.bam', 'sit': 'phase_6/models/char/pluto-sit.bam', 'stand': 'phase_6/models/char/pluto-stand.bam'}) elif charType == CIGlobals.Goofy: self.loadModel('phase_6/models/char/TT_G-1500.bam') self.loadAnims({'neutral': 'phase_6/models/char/TT_GWait.bam', 'walk': 'phase_6/models/char/TT_GWalk.bam'}) else: raise StandardError('unknown char %s!' % charType) Avatar.Avatar.initShadow(self) return def initializeLocalCollisions(self, name, radius): Avatar.Avatar.initializeLocalCollisions(self, radius, 2, name) def startBlink(self): randomStart = random.uniform(0.5, 5) taskMgr.add(self.blinkTask, 'blinkTask') def stopBlink(self): taskMgr.remove('blinkTask') taskMgr.remove('doBlink') taskMgr.remove('openEyes') def blinkTask(self, task): taskMgr.add(self.doBlink, 'doBlink') delay = random.uniform(0.5, 7) task.delayTime = delay return task.again def doBlink(self, task): self.closeEyes() taskMgr.doMethodLater(0.2, self.openEyes, 'openEyes') return task.done def closeEyes(self): self.find('**/joint_pupilR').hide() self.find('**/joint_pupilL').hide() if self.charType == CIGlobals.Mickey: self.mickeyEye.setY(-0.025) self.mickeyEye.hide() self.find('**/eyes').setTexture(self.closedEyes, 1) def openEyes(self, task): self.find('**/joint_pupilR').show() self.find('**/joint_pupilL').show() if self.charType == CIGlobals.Mickey: self.mickeyEye.setY(0.025) self.mickeyEye.show() self.find('**/eyes').setTexture(self.eyes, 1) return task.done def enterOff(self): self.currentAnim = None return def exitOff(self): pass def enterNeutral(self): self.loop('neutral') def exitNeutral(self): self.stop() def enterWalk(self): self.loop('walk') def exitWalk(self): self.stop() def enterRun(self): self.loop('run') def exitRun(self): self.stop()
class QuietZoneState(StateData): def __init__(self, doneEvent, moveOn=1): StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('quietZone', [ State('off', self.enterOff, self.exitOff, ['waitForQuietZoneResponse']), State( 'waitForQuietZoneResponse', self.enterWaitForQuietZoneResponse, self.exitWaitForQuietZoneResponse, ['waitForSetZoneResponse']), State('waitForSetZoneResponse', self.enterWaitForSetZoneResponse, self.exitWaitForSetZoneResponse, ['waitForSetZoneComplete']), State('waitForSetZoneComplete', self.enterWaitForSetZoneComplete, self.exitWaitForSetZoneComplete, ['off']) ], 'off', 'off') self.fsm.enterInitialState() self.moveOn = moveOn def getSetZoneCompleteEvent(self): return 'setZoneComplete-%s' % id(self) def getQuietZoneResponseEvent(self): return 'quietZoneResponse-%s' % id(self) def getEnterWaitForSetZoneResponseMsg(self): return 'enterWaitForSetZoneResponse-%s' % id(self) def unload(self): StateData.unload(self) del self.fsm def enter(self, requestStatus): StateData.enter(self) self._requestStatus = requestStatus base.localAvatar.b_setAnimState('off') self.fsm.request('waitForQuietZoneResponse') def exit(self): StateData.exit(self) if self._requestStatus.get('how', None) != 'doorOut': base.transitions.noTransitions() del self._requestStatus self.fsm.request('off') return def getDoneStatus(self): return self._requestStatus def enterOff(self): pass def exitOff(self): pass def handleWaitForQuietZoneResponse(self, msgType, di): if msgType == CLIENT_ENTER_OBJECT_REQUIRED: base.cr.handleQuietZoneGenerateWithRequired(di) else: if msgType == CLIENT_ENTER_OBJECT_REQUIRED_OTHER: base.cr.handleQuietZoneGenerateWithRequiredOther(di) else: if msgType == CLIENT_OBJECT_SET_FIELD: base.cr.handleQuietZoneUpdateField(di) else: base.cr.astronHandle(di) def enterWaitForQuietZoneResponse(self): self.setZoneDoneEvent = base.cr.getNextSetZoneDoneEvent() self.acceptOnce(self.setZoneDoneEvent, self._handleQuietZoneResponse) base.cr.sendQuietZoneRequest() def _handleQuietZoneResponse(self): if self.moveOn: self.fsm.request('waitForSetZoneResponse') else: messenger.send('enteredQuietZone') def exitWaitForQuietZoneResponse(self): self.ignore(self.setZoneDoneEvent) del self.setZoneDoneEvent def enterWaitForZoneRedirect(self): self.fsm.request('waitForSetZoneResponse') def exitWaitForZoneRedirect(self): pass def enterWaitForSetZoneResponse(self): zoneId = self._requestStatus['zoneId'] base.cr.sendSetZoneMsg(zoneId) self.fsm.request('waitForSetZoneComplete') def exitWaitForSetZoneResponse(self): pass def enterWaitForSetZoneComplete(self): self.setZoneDoneEvent = base.cr.getLastSetZoneDoneEvent() self.acceptOnce(self.setZoneDoneEvent, self._announceDone) def exitWaitForSetZoneComplete(self): self.ignore(self.setZoneDoneEvent) del self.setZoneDoneEvent def _announceDone(self): doneEvent = self.doneEvent requestStatus = self._requestStatus messenger.send(self.getSetZoneCompleteEvent(), [requestStatus]) messenger.send(doneEvent) def getRequestStatus(self): return self._requestStatus
class AvChooser(StateData): notify = directNotify.newCategory('AvChooser') def __init__(self, parentFSM): StateData.__init__(self, 'avChooseDone') self.avChooseFSM = ClassicFSM('avChoose', [State('getToonData', self.enterGetToonData, self.exitGetToonData), State('avChoose', self.enterAvChoose, self.exitAvChoose), State('waitForToonDelResponse', self.enterWaitForToonDelResponse, self.exitWaitForToonDelResponse), State('off', self.enterOff, self.exitOff)], 'off', 'off') self.avChooseFSM.enterInitialState() self.parentFSM = parentFSM self.parentFSM.getStateNamed('avChoose').addChild(self.avChooseFSM) self.pickAToon = None self.setAvatarsNone() return def enter(self): StateData.enter(self) base.transitions.noTransitions() self.avChooseFSM.request('getToonData') def exit(self): StateData.exit(self) self.setAvatarsNone() self.avChooseFSM.requestFinalState() def setAvatarsNone(self): self.avChoices = [] def enterOff(self): pass def exitOff(self): pass def enterGetToonData(self): self.acceptOnce(base.cr.csm.getSetAvatarsEvent(), self.handleToonData) base.cr.csm.d_requestAvatars() def handleToonData(self, avatarList): for av in avatarList: avId = av[0] dna = av[1] name = av[2] slot = av[3] choice = AvChoice(dna, name, slot, avId) self.avChoices.append(choice) self.avChooseFSM.request('avChoose') def exitGetToonData(self): self.ignore(base.cr.csm.getSetAvatarsEvent()) def enterAvChoose(self): self.pickAToon = CharSelection(self) self.pickAToon.load() def enterWaitForToonDelResponse(self, avId): self.acceptOnce(base.cr.csm.getToonDeletedEvent(), self.handleDeleteToonResp) base.cr.csm.sendDeleteToon(avId) def exitWaitForToonDelResponse(self): self.ignore(base.cr.csm.getToonDeletedEvent()) def hasToonInSlot(self, slot): if self.getAvChoiceBySlot(slot) != None: return True else: return False return def getNameInSlot(self, slot): return self.getAvChoiceBySlot(slot).getName() def getAvChoiceBySlot(self, slot): for avChoice in self.avChoices: if avChoice.getSlot() == slot: return avChoice return None def getHeadInfo(self, slot): dna = self.getAvChoiceBySlot(slot).getDNA() self.pickAToon.dna.setDNAStrand(dna) return [self.pickAToon.dna.getGender(), self.pickAToon.dna.getAnimal(), self.pickAToon.dna.getHead(), self.pickAToon.dna.getHeadColor()] def handleDeleteToonResp(self): base.cr.loginFSM.request('avChoose') def exitAvChoose(self): self.pickAToon.unload() self.pickAToon = None return
class DistributedDisneyChar(DistributedAvatar, DistributedSmoothNode): notify = directNotify.newCategory('DistributedDisneyChar') def __init__(self, cr): DistributedAvatar.__init__(self, cr) DistributedSmoothNode.__init__(self, cr) self.fsm = ClassicFSM('DDisneyChar', [ State('off', self.enterOff, self.exitOff), State('walking', self.enterWalking, self.exitWalking), State('neutral', self.enterNeutral, self.exitNeutral) ], 'off', 'off') self.fsm.enterInitialState() self.neutralFSM = ClassicFSM('DDisneyChar-neutral', [ State('off', self.enterOff, self.exitOff), State('turn2target', self.enterTurn2Target, self.exitTurn2Target), State('talk2target', self.enterTalk2Target, self.exitTalk2Target) ], 'off', 'off') self.neutralFSM.enterInitialState() self.charId = 0 self.geoEyes = 0 self.avatarType = CIGlobals.CChar self.isInRange = False self.currentPointLetter = "a" self.walkIval = None self.currentChat = "" self.talkEnabled = True self.speechSound = None self.chatsSinceLastNoise = 0 self.chatsWithoutNoise = 5 self.eyes = None self.lpupil = None self.rpupil = None self.eyesOpen = None self.eyesClosed = None def setCharId(self, charId): self.charId = charId def enterOff(self): pass def exitOff(self): pass def doNeutral(self, pointLetter): self.fsm.request('neutral', [pointLetter]) def doWalking(self, pointLetter, startPointLetter, timestamp): ts = globalClockDelta.localElapsedTime(timestamp) self.fsm.request('walking', [pointLetter, startPointLetter, ts]) def enterWalking(self, pointLetter, startPointLetter, ts): if self.walkIval: self.walkIval.finish() self.walkIval = None self.nametag.clearChatText() self.loop('walk') point = WALK_POINTS[self.charId][pointLetter][0] lastPoint = WALK_POINTS[self.charId][startPointLetter][0] seq = Sequence(name=self.uniqueName('DCharWalkIval')) if self.charId == PLUTO: seq.append(ActorInterval(self, 'stand')) elif self.charId == SLEEP_DONALD: seq.append(ActorInterval(self, 'neutral2walk')) seq.append(Func(self.loop, 'walk')) ival = NPCWalkInterval(self, point, startPos=lastPoint, fluid=1) seq.append(ival) seq.append(Func(self.loop, 'neutral')) seq.start(ts) self.currentPointLetter = pointLetter self.walkIval = ival def exitWalking(self): if self.walkIval: self.walkIval.finish() self.walkIval = None def enterNeutral(self, pointLetter): point = WALK_POINTS[self.charId][pointLetter][0] self.setPos(point) if self.charId == PLUTO: seq = Sequence(ActorInterval(self, 'sit'), Func(self.loop, 'neutral')) seq.start() elif self.charId == SLEEP_DONALD: seq = Sequence(ActorInterval(self, 'walk2neutral'), Func(self.loop, 'neutral')) seq.start() else: self.loop('neutral') def talk2Toon(self, chatType, chatIndex, avId): toon = self.cr.doId2do.get(avId) if not toon: return if chatType in [SHARED_GREETINGS, SHARED_COMMENTS, SHARED_GOODBYES]: self.currentChat = CHATTER[chatType][chatIndex] elif chatType in [CHAR_GREETINGS, CHAR_COMMENTS, CHAR_GOODBYES]: self.currentChat = CHATTER[chatType][self.charId][chatIndex] if '%s' in self.currentChat: self.currentChat = self.currentChat % toon.getName() self.neutralFSM.request('turn2target', [toon]) def enterTurn2Target(self, toon): self.turnIval = NPCLookInterval(self, toon, fluid=1, name=self.uniqueName('turnIval')) if self.turnIval.distance > 30: self.loop('walk') elif self.turnIval.distance < 10.0: self.headsUp(toon) self.neutralFSM.request('talk2target') return self.turnIval.setDoneEvent(self.turnIval.getName()) self.acceptOnce(self.turnIval.getDoneEvent(), self.__handleTurningDone) self.turnIval.start() def __handleTurningDone(self): self.neutralFSM.request('talk2target') def exitTurn2Target(self): self.ignore(self.turnIval.getDoneEvent()) self.turnIval.finish() del self.turnIval def enterTalk2Target(self): self.setChat(self.currentChat) if self.getCurrentAnim() != 'neutral': if self.charId == SLEEP_DONALD: seq = Sequence(ActorInterval(self, 'walk2neutral'), Func(self.loop, 'neutral')) seq.start() else: self.loop('neutral') def exitTalk2Target(self): pass def exitNeutral(self): self.neutralFSM.request('off') self.stop() def setChat(self, chat): if self.charId == SLEEP_DONALD: chat = "." + chat DistributedAvatar.setChat(self, chat) if self.chatsSinceLastNoise >= self.chatsWithoutNoise or self.chatsSinceLastNoise == 0: base.playSfx(self.speechSound, node=self) self.chatsSinceLastNoise = 0 self.chatsWithoutNoise = random.randint(1, 5) self.chatsSinceLastNoise += 1 def loadChar(self): data = CHAR_DATA[self.charId] self.loadModel(data[0], 'modelRoot') self.loadAnims(data[1], 'modelRoot') if self.charId == SLEEP_DONALD: self.setPlayRate(0.5, 'neutral') self.setHeight(data[2]) self.setName(data[3]) self.talkEnabled = data[4] if self.talkEnabled: self.speechSound = data[5] if self.speechSound is not None: base.audio3d.attachSoundToObject(self.speechSound, self) self.setupNameTag() self.ears = [] if self.charId in [MINNIE, MICKEY]: for bundle in self.getPartBundleDict().values(): bundle = bundle['modelRoot'].getBundle() earNull = bundle.findChild('sphere3') if not earNull: earNull = bundle.findChild('*sphere3') earNull.clearNetTransforms() for bundle in self.getPartBundleDict().values(): charNodepath = bundle['modelRoot'].partBundleNP bundle = bundle['modelRoot'].getBundle() earNull = bundle.findChild('sphere3') if not earNull: earNull = bundle.findChild('*sphere3') ears = charNodepath.find('**/sphere3') if ears.isEmpty(): ears = charNodepath.find('**/*sphere3') ears.clearEffect(CharacterJointEffect.getClassType()) earRoot = charNodepath.attachNewNode('earRoot') earPitch = earRoot.attachNewNode('earPitch') earPitch.setP(40.0) ears.reparentTo(earPitch) earNull.addNetTransform(earRoot.node()) ears.clearMat() ears.node().setPreserveTransform(ModelNode.PTNone) ears.setP(-40.0) ears.flattenMedium() self.ears.append(ears) ears.setBillboardAxis() self.eyesOpen = loader.loadTexture('phase_3/maps/eyes1.jpg', 'phase_3/maps/eyes1_a.rgb') self.eyesClosed = loader.loadTexture( 'phase_3/maps/mickey_eyes_closed.jpg', 'phase_3/maps/mickey_eyes_closed_a.rgb') self.eyes = self.find('**/eyes') self.eyes.setBin('transparent', 0) self.lpupil = self.find('**/joint_pupilL') self.rpupil = self.find('**/joint_pupilR') self.drawInFront('joint_pupil?', 'eyes*', -3) elif self.charId == PLUTO: self.eyesOpen = loader.loadTexture( 'phase_6/maps/plutoEyesOpen.jpg', 'phase_6/maps/plutoEyesOpen_a.rgb') self.eyesClosed = loader.loadTexture( 'phase_6/maps/plutoEyesClosed.jpg', 'phase_6/maps/plutoEyesClosed_a.rgb') self.eyes = self.find('**/eyes') self.lpupil = self.find('**/joint_pupilL') self.rpupil = self.find('**/joint_pupilR') self.drawInFront('joint_pupil?', 'eyes*', -3) elif self.charId == DAISY: self.geoEyes = 1 self.eyeOpenList = [] self.eyeCloseList = [] self.eyeCloseList.append(self.find('**/eyesclose')) self.eyeOpenList.append(self.find('**/eyesclose')) self.eyeOpenList.append(self.find('**/eyespupil')) self.eyeOpenList.append(self.find('**/eyesopen')) for part in self.eyeOpenList: part.show() for part in self.eyeCloseList: part.hide() elif self.charId == SAILOR_DONALD: self.eyes = self.find('**/eyes') self.lpupil = self.find('**/joint_pupilL') self.rpupil = self.find('**/joint_pupilR') self.drawInFront('joint_pupil?', 'eyes*', -3) if self.lpupil is not None: self.lpupil.adjustAllPriorities(1) self.rpupil.adjustAllPriorities(1) if self.eyesOpen: self.eyesOpen.setMinfilter(Texture.FTLinear) self.eyesOpen.setMagfilter(Texture.FTLinear) if self.eyesClosed: self.eyesClosed.setMinfilter(Texture.FTLinear) self.eyesClosed.setMagfilter(Texture.FTLinear) if self.charId == MICKEY: pupilParent = self.rpupil.getParent() pupilOffsetNode = pupilParent.attachNewNode('pupilOffsetNode') pupilOffsetNode.setPos(0, 0.025, 0) self.rpupil.reparentTo(pupilOffsetNode) self.initShadow() self.shadow.setScale(0.6) self.initializeBodyCollisions(self.avatarType, self.getHeight(), 1.0) self.initializeRay(self.avatarType, 1) self.disableShadowRay() self.__blinkName = 'blink-' + data[3] def setupNameTag(self): DistributedAvatar.setupNameTag(self) self.nametag.setNametagColor( NametagGlobals.NametagColors[NametagGlobals.CCNPC]) self.nametag.setActive(0) self.nametag.updateAll() def __monitorRange(self, task): if base.localAvatar.getDistance(self) <= MAX_RANGE: if self.isInRange is False: self.sendUpdate('avatarEnter') self.isInRange = True else: if self.isInRange is True: self.sendUpdate('avatarExit') self.isInRange = False return task.cont def __blinkOpenEyes(self, task): self.openEyes() r = random.random() if r < 0.1: t = 0.2 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self.__blinkCloseEyes, self.__blinkName) return task.done def __blinkCloseEyes(self, task): self.closeEyes() taskMgr.doMethodLater(0.125, self.__blinkOpenEyes, self.__blinkName) return task.done def openEyes(self): if self.geoEyes: for part in self.eyeOpenList: part.show() for part in self.eyeCloseList: part.hide() else: if self.eyes: self.eyes.setTexture(self.eyesOpen, 1) self.lpupil.show() self.rpupil.show() def closeEyes(self): if self.geoEyes: for part in self.eyeOpenList: part.hide() for part in self.eyeCloseList: part.show() else: if self.eyes: self.eyes.setTexture(self.eyesClosed, 1) self.lpupil.hide() self.rpupil.hide() def startBlink(self): if self.eyesOpen or self.geoEyes: taskMgr.remove(self.__blinkName) taskMgr.doMethodLater(random.random() * 4 + 1, self.__blinkCloseEyes, self.__blinkName) def stopBlink(self): if self.eyesOpen or self.geoEyes: taskMgr.remove(self.__blinkName) self.openEyes() def getNametagJoints(self): return [] def generate(self): DistributedAvatar.generate(self) DistributedSmoothNode.generate(self) def announceGenerate(self): DistributedAvatar.announceGenerate(self) DistributedSmoothNode.announceGenerate(self) self.loadChar() self.startBlink() base.taskMgr.add(self.__monitorRange, self.uniqueName('monitorRange')) self.sendUpdate('requestStateData') if self.charId == SAILOR_DONALD: self.disableRay() self.stashBodyCollisions() boat = self.cr.playGame.hood.loader.geom.find('**/*donalds_boat*') boat.find('**/wheel').hide() self.setPos(0, -1, 3.95) self.reparentTo(boat) self.loop('wheel') else: self.reparentTo(render) def disable(self): base.taskMgr.remove(self.uniqueName('monitorRange')) self.stopBlink() self.fsm.requestFinalState() self.fsm = None self.neutralFSM.requestFinalState() self.neutralFSM = None self.charId = None self.geoEyes = None self.avatarType = None self.isInRange = None self.currentPointLetter = None self.walkIval = None self.currentChat = None self.talkEnabled = None self.speechSound = None self.chatsSinceLastNoise = None self.eyes = None self.lpupil = None self.rpupil = None self.eyesOpen = None self.eyesClosed = None DistributedAvatar.disable(self) Avatar.disable(self) DistributedSmoothNode.disable(self)
class ToonHead(Actor.Actor): notify = DirectNotifyGlobal.directNotify.newCategory('ToonHead') EyesOpen = loader.loadTexture('phase_3/maps/eyes.jpg', 'phase_3/maps/eyes_a.rgb') EyesOpen.setMinfilter(Texture.FTLinear) EyesOpen.setMagfilter(Texture.FTLinear) EyesClosed = loader.loadTexture('phase_3/maps/eyesClosed.jpg', 'phase_3/maps/eyesClosed_a.rgb') EyesClosed.setMinfilter(Texture.FTLinear) EyesClosed.setMagfilter(Texture.FTLinear) EyesSadOpen = loader.loadTexture('phase_3/maps/eyesSad.jpg', 'phase_3/maps/eyesSad_a.rgb') EyesSadOpen.setMinfilter(Texture.FTLinear) EyesSadOpen.setMagfilter(Texture.FTLinear) EyesSadClosed = loader.loadTexture('phase_3/maps/eyesSadClosed.jpg', 'phase_3/maps/eyesSadClosed_a.rgb') EyesSadClosed.setMinfilter(Texture.FTLinear) EyesSadClosed.setMagfilter(Texture.FTLinear) EyesAngryOpen = loader.loadTexture('phase_3/maps/eyesAngry.jpg', 'phase_3/maps/eyesAngry_a.rgb') EyesAngryOpen.setMinfilter(Texture.FTLinear) EyesAngryOpen.setMagfilter(Texture.FTLinear) EyesAngryClosed = loader.loadTexture('phase_3/maps/eyesAngryClosed.jpg', 'phase_3/maps/eyesAngryClosed_a.rgb') EyesAngryClosed.setMinfilter(Texture.FTLinear) EyesAngryClosed.setMagfilter(Texture.FTLinear) EyesSurprised = loader.loadTexture('phase_3/maps/eyesSurprised.jpg', 'phase_3/maps/eyesSurprised_a.rgb') EyesSurprised.setMinfilter(Texture.FTLinear) EyesSurprised.setMagfilter(Texture.FTLinear) Muzzle = loader.loadTexture('phase_3/maps/muzzleShrtGeneric.jpg') Muzzle.setMinfilter(Texture.FTLinear) Muzzle.setMagfilter(Texture.FTLinear) MuzzleSurprised = loader.loadTexture('phase_3/maps/muzzleShortSurprised.jpg') MuzzleSurprised.setMinfilter(Texture.FTLinear) MuzzleSurprised.setMagfilter(Texture.FTLinear) LeftA = Point3(0.06, 0.0, 0.14) LeftB = Point3(-0.13, 0.0, 0.1) LeftC = Point3(-0.05, 0.0, 0.0) LeftD = Point3(0.06, 0.0, 0.0) RightA = Point3(0.13, 0.0, 0.1) RightB = Point3(-0.06, 0.0, 0.14) RightC = Point3(-0.06, 0.0, 0.0) RightD = Point3(0.05, 0.0, 0.0) LeftAD = Point3(LeftA[0] - LeftA[2] * (LeftD[0] - LeftA[0]) / (LeftD[2] - LeftA[2]), 0.0, 0.0) LeftBC = Point3(LeftB[0] - LeftB[2] * (LeftC[0] - LeftB[0]) / (LeftC[2] - LeftB[2]), 0.0, 0.0) RightAD = Point3(RightA[0] - RightA[2] * (RightD[0] - RightA[0]) / (RightD[2] - RightA[2]), 0.0, 0.0) RightBC = Point3(RightB[0] - RightB[2] * (RightC[0] - RightB[0]) / (RightC[2] - RightB[2]), 0.0, 0.0) def __init__(self): try: self.ToonHead_initialized except: self.ToonHead_initialized = 1 Actor.Actor.__init__(self) self.toonName = 'ToonHead-' + str(self.this) self.__blinkName = 'blink-' + self.toonName self.__stareAtName = 'stareAt-' + self.toonName self.__lookName = 'look-' + self.toonName self.lookAtTrack = None self.__eyes = None self.__eyelashOpen = None self.__eyelashClosed = None self.__lod500Eyes = None self.__lod250Eyes = None self.__lpupil = None self.__lod500lPupil = None self.__lod250lPupil = None self.__rpupil = None self.__lod500rPupil = None self.__lod250rPupil = None self.__muzzle = None self.__eyesOpen = ToonHead.EyesOpen self.__eyesClosed = ToonHead.EyesClosed self.__height = 0.0 self.__eyelashesHiddenByGlasses = False self.randGen = random.Random() self.randGen.seed(random.random()) self.eyelids = ClassicFSM('eyelids', [ State('off', self.enterEyelidsOff, self.exitEyelidsOff, ['open', 'closed', 'surprised']), State('open', self.enterEyelidsOpen, self.exitEyelidsOpen, ['closed', 'surprised', 'off']), State('surprised', self.enterEyelidsSurprised, self.exitEyelidsSurprised, ['open', 'closed', 'off']), State('closed', self.enterEyelidsClosed, self.exitEyelidsClosed, ['open', 'surprised', 'off']) ], 'off', 'off') self.eyelids.enterInitialState() self.emote = None self.__stareAtNode = NodePath() self.__defaultStarePoint = Point3(0, 0, 0) self.__stareAtPoint = self.__defaultStarePoint self.__stareAtTime = 0 self.lookAtPositionCallbackArgs = None def delete(self): try: self.ToonHead_deleted except: self.ToonHead_deleted = 1 taskMgr.remove(self.__blinkName) taskMgr.remove(self.__lookName) taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None del self.eyelids del self.__stareAtNode del self.__stareAtPoint if self.__eyes: del self.__eyes if self.__lpupil: del self.__lpupil if self.__rpupil: del self.__rpupil if self.__eyelashOpen: del self.__eyelashOpen if self.__eyelashClosed: del self.__eyelashClosed self.lookAtPositionCallbackArgs = None Actor.Actor.delete(self) def setupHead(self, dna, forGui = 0): self.__height = self.generateToonHead(1, dna, ('1000',), forGui) self.generateToonColor(dna) animalStyle = dna.getAnimal() bodyScale = ToontownGlobals.toonBodyScales[animalStyle] headScale = ToontownGlobals.toonHeadScales[animalStyle] self.getGeomNode().setScale(headScale[0] * bodyScale * 1.3, headScale[1] * bodyScale * 1.3, headScale[2] * bodyScale * 1.3) if forGui: self.getGeomNode().setDepthWrite(1) self.getGeomNode().setDepthTest(1) if dna.getAnimal() == 'dog': self.loop('neutral') def fitAndCenterHead(self, maxDim, forGui = 0): p1 = Point3() p2 = Point3() self.calcTightBounds(p1, p2) if forGui: h = 180 t = p1[0] p1.setX(-p2[0]) p2.setX(-t) else: h = 0 d = p2 - p1 biggest = max(d[0], d[2]) s = maxDim / biggest mid = (p1 + d / 2.0) * s self.setPosHprScale(-mid[0], -mid[1] + 1, -mid[2], h, 0, 0, s, s, s) def setLookAtPositionCallbackArgs(self, argTuple): self.lookAtPositionCallbackArgs = argTuple def getHeight(self): return self.__height def getRandomForwardLookAtPoint(self): x = self.randGen.choice((-0.8, -0.5, 0, 0.5, 0.8)) z = self.randGen.choice((-0.5, 0, 0.5, 0.8)) return Point3(x, 1.5, z) def findSomethingToLookAt(self): if self.lookAtPositionCallbackArgs != None: pnt = self.lookAtPositionCallbackArgs[0].getLookAtPosition(self.lookAtPositionCallbackArgs[1], self.lookAtPositionCallbackArgs[2]) self.startStareAt(self, pnt) return if self.randGen.random() < 0.33: lookAtPnt = self.getRandomForwardLookAtPoint() else: lookAtPnt = self.__defaultStarePoint self.lerpLookAt(lookAtPnt, blink=1) def generateToonHead(self, copy, style, lods, forGui=0): headStyle = style.head fix = None if headStyle == 'dls': filePrefix = HeadDict['dls'] headHeight = 0.75 elif headStyle == 'dss': filePrefix = HeadDict['dss'] headHeight = 0.5 elif headStyle == 'dsl': filePrefix = HeadDict['dsl'] headHeight = 0.5 elif headStyle == 'dll': filePrefix = HeadDict['dll'] headHeight = 0.75 elif headStyle == 'cls': filePrefix = HeadDict['c'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'css': filePrefix = HeadDict['c'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'csl': filePrefix = HeadDict['c'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'cll': filePrefix = HeadDict['c'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'hls': filePrefix = HeadDict['h'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'hss': filePrefix = HeadDict['h'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'hsl': filePrefix = HeadDict['h'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'hll': filePrefix = HeadDict['h'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'mls': filePrefix = HeadDict['m'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'mss': filePrefix = HeadDict['m'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'rls': filePrefix = HeadDict['r'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'rss': filePrefix = HeadDict['r'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'rsl': filePrefix = HeadDict['r'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'rll': filePrefix = HeadDict['r'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'fls': filePrefix = HeadDict['f'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'fss': filePrefix = HeadDict['f'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'fsl': filePrefix = HeadDict['f'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'fll': filePrefix = HeadDict['f'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'pls': filePrefix = HeadDict['p'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'pss': filePrefix = HeadDict['p'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'psl': filePrefix = HeadDict['p'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'pll': filePrefix = HeadDict['p'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'bls': filePrefix = HeadDict['b'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'bss': filePrefix = HeadDict['b'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'bsl': filePrefix = HeadDict['b'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'bll': filePrefix = HeadDict['b'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'sls': filePrefix = HeadDict['s'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'sss': filePrefix = HeadDict['s'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'ssl': filePrefix = HeadDict['s'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'sll': filePrefix = HeadDict['s'] fix = self.__fixHeadLongLong headHeight = 0.75 else: ToonHead.notify.error('unknown head style: %s' % headStyle) if len(lods) == 1: self.loadModel('phase_3' + filePrefix + lods[0], 'head', 'lodRoot', copy) if not copy: self.showAllParts('head') if fix != None: fix(style, None, copy) if not forGui: self.__lods = lods self.__style = style self.__headStyle = headStyle self.__copy = copy else: for lod in lods: self.loadModel('phase_3' + filePrefix + lod, 'head', lod, copy) if not copy: self.showAllParts('head', lod) if fix != None: fix(style, lod, copy) if not forGui: self.__lods = lods self.__style = style self.__headStyle = headStyle self.__copy = copy self.__fixEyes(style, forGui) self.setupEyelashes(style) self.eyelids.request('closed') self.eyelids.request('open') self.setupMuzzles(style) return headHeight def hideEars(self): self.findAllMatches('**/ears*;+s').stash() def showEars(self): self.findAllMatches('**/ears*;+s').unstash() def hideEyelashes(self): if self.__eyelashOpen: self.__eyelashOpen.stash() if self.__eyelashClosed: self.__eyelashClosed.stash() self.__eyelashesHiddenByGlasses = True def showEyelashes(self): if self.__eyelashOpen: self.__eyelashOpen.unstash() if self.__eyelashClosed: self.__eyelashClosed.unstash() self.__eyelashesHiddenByGlasses = False def generateToonColor(self, style): parts = self.findAllMatches('**/head*') parts.setColor(style.getHeadColor()) animalType = style.getAnimal() if animalType == 'cat' or animalType == 'rabbit' or animalType == 'bear' or animalType == 'mouse' or animalType == 'pig': parts = self.findAllMatches('**/ear?-*') parts.setColor(style.getHeadColor()) def __fixEyes(self, style, forGui = 0): mode = -3 if forGui: mode = -2 if self.hasLOD(): for lodName in self.getLODNames(): self.drawInFront('eyes*', 'head-front*', mode, lodName=lodName) if base.config.GetBool('want-new-anims', 1): if not self.find('**/joint_pupil*').isEmpty(): self.drawInFront('joint_pupil*', 'eyes*', -1, lodName=lodName) else: self.drawInFront('def_*_pupil', 'eyes*', -1, lodName=lodName) else: self.drawInFront('joint_pupil*', 'eyes*', -1, lodName=lodName) self.__eyes = self.getLOD(1000).find('**/eyes*') self.__lod500Eyes = self.getLOD(500).find('**/eyes*') self.__lod250Eyes = self.getLOD(250).find('**/eyes*') if self.__lod500Eyes.isEmpty(): self.__lod500Eyes = None else: self.__lod500Eyes.setColorOff() if base.config.GetBool('want-new-anims', 1): if not self.find('**/joint_pupilL*').isEmpty(): self.__lod500lPupil = self.__lod500Eyes.find('**/joint_pupilL*') self.__lod500rPupil = self.__lod500Eyes.find('**/joint_pupilR*') else: self.__lod500lPupil = self.__lod500Eyes.find('**/def_left_pupil*') self.__lod500rPupil = self.__lod500Eyes.find('**/def_right_pupil*') else: self.__lod500lPupil = self.__lod500Eyes.find('**/joint_pupilL*') self.__lod500rPupil = self.__lod500Eyes.find('**/joint_pupilR*') if self.__lod250Eyes.isEmpty(): self.__lod250Eyes = None else: self.__lod250Eyes.setColorOff() if base.config.GetBool('want-new-anims', 1): if not self.find('**/joint_pupilL*').isEmpty(): self.__lod250lPupil = self.__lod250Eyes.find('**/joint_pupilL*') self.__lod250rPupil = self.__lod250Eyes.find('**/joint_pupilR*') else: self.__lod250lPupil = self.__lod250Eyes.find('**/def_left_pupil*') self.__lod250rPupil = self.__lod250Eyes.find('**/def_right_pupil*') else: self.__lod250lPupil = self.__lod250Eyes.find('**/joint_pupilL*') self.__lod250rPupil = self.__lod250Eyes.find('**/joint_pupilR*') else: self.drawInFront('eyes*', 'head-front*', mode) if base.config.GetBool('want-new-anims', 1): if not self.find('joint_pupil*').isEmpty(): self.drawInFront('joint_pupil*', 'eyes*', -1) else: self.drawInFront('def_*_pupil', 'eyes*', -1) else: self.drawInFront('joint_pupil*', 'eyes*', -1) self.__eyes = self.find('**/eyes*') if not self.__eyes.isEmpty(): self.__eyes.setColorOff() self.__lpupil = None self.__rpupil = None if base.config.GetBool('want-new-anims', 1): if not self.find('**/joint_pupilL*').isEmpty(): if self.getLOD(1000): lp = self.getLOD(1000).find('**/joint_pupilL*') rp = self.getLOD(1000).find('**/joint_pupilR*') else: lp = self.find('**/joint_pupilL*') rp = self.find('**/joint_pupilR*') elif not self.getLOD(1000): lp = self.find('**/def_left_pupil*') rp = self.find('**/def_right_pupil*') else: lp = self.getLOD(1000).find('**/def_left_pupil*') rp = self.getLOD(1000).find('**/def_right_pupil*') else: lp = self.__eyes.find('**/joint_pupilL*') rp = self.__eyes.find('**/joint_pupilR*') if lp.isEmpty() or rp.isEmpty(): print 'Unable to locate pupils.' else: leye = self.__eyes.attachNewNode('leye') reye = self.__eyes.attachNewNode('reye') lmat = Mat4(0.802174, 0.59709, 0, 0, -0.586191, 0.787531, 0.190197, 0, 0.113565, -0.152571, 0.981746, 0, -0.233634, 0.418062, 0.0196875, 1) leye.setMat(lmat) rmat = Mat4(0.786788, -0.617224, 0, 0, 0.602836, 0.768447, 0.214658, 0, -0.132492, -0.16889, 0.976689, 0, 0.233634, 0.418062, 0.0196875, 1) reye.setMat(rmat) self.__lpupil = leye.attachNewNode('lpupil') self.__rpupil = reye.attachNewNode('rpupil') lpt = self.__eyes.attachNewNode('') rpt = self.__eyes.attachNewNode('') lpt.wrtReparentTo(self.__lpupil) rpt.wrtReparentTo(self.__rpupil) lp.reparentTo(lpt) rp.reparentTo(rpt) self.__lpupil.adjustAllPriorities(1) self.__rpupil.adjustAllPriorities(1) if self.__lod500Eyes: self.__lod500lPupil.adjustAllPriorities(1) self.__lod500rPupil.adjustAllPriorities(1) if self.__lod250Eyes: self.__lod250lPupil.adjustAllPriorities(1) self.__lod250rPupil.adjustAllPriorities(1) animalType = style.getAnimal() if animalType != 'dog': self.__lpupil.flattenStrong() self.__rpupil.flattenStrong() return def __setPupilDirection(self, x, y): if y < 0.0: y2 = -y left1 = self.LeftAD + (self.LeftD - self.LeftAD) * y2 left2 = self.LeftBC + (self.LeftC - self.LeftBC) * y2 right1 = self.RightAD + (self.RightD - self.RightAD) * y2 right2 = self.RightBC + (self.RightC - self.RightBC) * y2 else: y2 = y left1 = self.LeftAD + (self.LeftA - self.LeftAD) * y2 left2 = self.LeftBC + (self.LeftB - self.LeftBC) * y2 right1 = self.RightAD + (self.RightA - self.RightAD) * y2 right2 = self.RightBC + (self.RightB - self.RightBC) * y2 left0 = Point3(0.0, 0.0, left1[2] - left1[0] * (left2[2] - left1[2]) / (left2[0] - left1[0])) right0 = Point3(0.0, 0.0, right1[2] - right1[0] * (right2[2] - right1[2]) / (right2[0] - right1[0])) if x < 0.0: x2 = -x left = left0 + (left2 - left0) * x2 right = right0 + (right2 - right0) * x2 else: x2 = x left = left0 + (left1 - left0) * x2 right = right0 + (right1 - right0) * x2 self.__lpupil.setPos(left) self.__rpupil.setPos(right) def __lookPupilsAt(self, node, point): if node != None: mat = node.getMat(self.__eyes) point = mat.xformPoint(point) distance = 1.0 recip_z = 1.0 / max(0.1, point[1]) x = distance * point[0] * recip_z y = distance * point[2] * recip_z x = min(max(x, -1), 1) y = min(max(y, -1), 1) self.__setPupilDirection(x, y) return def __lookHeadAt(self, node, point, frac = 1.0, lod = None): reachedTarget = 1 if lod == None: head = self.getPart('head', self.getLODNames()[0]) else: head = self.getPart('head', lod) if node != None: headParent = head.getParent() mat = node.getMat(headParent) point = mat.xformPoint(point) rot = Mat3(0, 0, 0, 0, 0, 0, 0, 0, 0) lookAt(rot, Vec3(point), Vec3(0, 0, 1), CSDefault) scale = VBase3(0, 0, 0) hpr = VBase3(0, 0, 0) if decomposeMatrix(rot, scale, hpr, CSDefault): hpr = VBase3(min(max(hpr[0], -60), 60), min(max(hpr[1], -20), 30), 0) if frac != 1: currentHpr = head.getHpr() reachedTarget = abs(hpr[0] - currentHpr[0]) < 1.0 and abs(hpr[1] - currentHpr[1]) < 1.0 hpr = currentHpr + (hpr - currentHpr) * frac if lod == None: for lodName in self.getLODNames(): head = self.getPart('head', lodName) head.setHpr(hpr) else: head.setHpr(hpr) return reachedTarget def setupEyelashes(self, style): if style.getGender() == 'm': if self.__eyelashOpen: self.__eyelashOpen.removeNode() self.__eyelashOpen = None if self.__eyelashClosed: self.__eyelashClosed.removeNode() self.__eyelashClosed = None else: if self.__eyelashOpen: self.__eyelashOpen.removeNode() if self.__eyelashClosed: self.__eyelashClosed.removeNode() animal = style.head[0] model = loader.loadModel('phase_3' + EyelashDict[animal]) if self.hasLOD(): head = self.getPart('head', '1000') else: head = self.getPart('head', 'lodRoot') length = style.head[1] if length == 'l': openString = 'open-long' closedString = 'closed-long' else: openString = 'open-short' closedString = 'closed-short' self.__eyelashOpen = model.find('**/' + openString).copyTo(head) self.__eyelashClosed = model.find('**/' + closedString).copyTo(head) model.removeNode() return def __fixHeadLongLong(self, style, lodName=None, copy=1): if lodName == None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) otherParts = searchRoot.findAllMatches('**/*short*') for partNum in range(0, otherParts.getNumPaths()): if copy: otherParts.getPath(partNum).removeNode() else: otherParts.getPath(partNum).stash() def __fixHeadLongShort(self, style, lodName=None, copy=1): animalType = style.getAnimal() headStyle = style.head if lodName == None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) if animalType != 'duck' and animalType != 'horse': if animalType == 'rabbit': if copy: searchRoot.find('**/ears-long').removeNode() else: searchRoot.find('**/ears-long').hide() elif copy: searchRoot.find('**/ears-short').removeNode() else: searchRoot.find('**/ears-short').hide() if animalType != 'rabbit': if copy: searchRoot.find('**/eyes-short').removeNode() else: searchRoot.find('**/eyes-short').hide() if animalType != 'dog': if copy: searchRoot.find('**/joint_pupilL_short').removeNode() searchRoot.find('**/joint_pupilR_short').removeNode() else: searchRoot.find('**/joint_pupilL_short').stash() searchRoot.find('**/joint_pupilR_short').stash() if copy: self.find('**/head-short').removeNode() self.find('**/head-front-short').removeNode() else: self.find('**/head-short').hide() self.find('**/head-front-short').hide() if animalType != 'rabbit': muzzleParts = searchRoot.findAllMatches('**/muzzle-long*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() else: muzzleParts = searchRoot.findAllMatches('**/muzzle-short*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() def __fixHeadShortLong(self, style, lodName=None, copy=1): animalType = style.getAnimal() headStyle = style.head if lodName == None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) if animalType != 'duck' and animalType != 'horse': if animalType == 'rabbit': if copy: searchRoot.find('**/ears-short').removeNode() else: searchRoot.find('**/ears-short').hide() elif copy: searchRoot.find('**/ears-long').removeNode() else: searchRoot.find('**/ears-long').hide() if animalType != 'rabbit': if copy: searchRoot.find('**/eyes-long').removeNode() else: searchRoot.find('**/eyes-long').hide() if animalType != 'dog': if copy: searchRoot.find('**/joint_pupilL_long').removeNode() searchRoot.find('**/joint_pupilR_long').removeNode() else: searchRoot.find('**/joint_pupilL_long').stash() searchRoot.find('**/joint_pupilR_long').stash() if copy: searchRoot.find('**/head-long').removeNode() searchRoot.find('**/head-front-long').removeNode() else: searchRoot.find('**/head-long').hide() searchRoot.find('**/head-front-long').hide() if animalType != 'rabbit': muzzleParts = searchRoot.findAllMatches('**/muzzle-short*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() else: muzzleParts = searchRoot.findAllMatches('**/muzzle-long*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() def __fixHeadShortShort(self, style, lodName=None, copy=1): if lodName == None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) otherParts = searchRoot.findAllMatches('**/*long*') for partNum in range(0, otherParts.getNumPaths()): if copy: otherParts.getPath(partNum).removeNode() else: otherParts.getPath(partNum).stash() def __blinkOpenEyes(self, task): if self.eyelids.getCurrentState().getName() == 'closed': self.eyelids.request('open') r = self.randGen.random() if r < 0.1: t = 0.2 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self.__blinkCloseEyes, self.__blinkName) return Task.done def __blinkCloseEyes(self, task): if self.eyelids.getCurrentState().getName() != 'open': taskMgr.doMethodLater(4.0, self.__blinkCloseEyes, self.__blinkName) else: self.eyelids.request('closed') taskMgr.doMethodLater(0.125, self.__blinkOpenEyes, self.__blinkName) return Task.done def startBlink(self): taskMgr.remove(self.__blinkName) if self.__eyes: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self.__blinkCloseEyes, self.__blinkName) def stopBlink(self): taskMgr.remove(self.__blinkName) if self.__eyes: self.eyelids.request('open') def closeEyes(self): self.eyelids.request('closed') def openEyes(self): self.eyelids.request('open') def surpriseEyes(self): self.eyelids.request('surprised') def sadEyes(self): self.__eyesOpen = ToonHead.EyesSadOpen self.__eyesClosed = ToonHead.EyesSadClosed def angryEyes(self): self.__eyesOpen = ToonHead.EyesAngryOpen self.__eyesClosed = ToonHead.EyesAngryClosed def normalEyes(self): self.__eyesOpen = ToonHead.EyesOpen self.__eyesClosed = ToonHead.EyesClosed def blinkEyes(self): taskMgr.remove(self.__blinkName) self.eyelids.request('closed') taskMgr.doMethodLater(0.1, self.__blinkOpenEyes, self.__blinkName) def __stareAt(self, task): frac = 2 * globalClock.getDt() reachedTarget = self.__lookHeadAt(self.__stareAtNode, self.__stareAtPoint, frac) self.__lookPupilsAt(self.__stareAtNode, self.__stareAtPoint) if reachedTarget and self.__stareAtNode == None: return Task.done else: return Task.cont return def doLookAroundToStareAt(self, node, point): self.startStareAt(node, point) self.startLookAround() def startStareAtHeadPoint(self, point): self.startStareAt(self, point) def startStareAt(self, node, point): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None self.__stareAtNode = node if point != None: self.__stareAtPoint = point else: self.__stareAtPoint = self.__defaultStarePoint self.__stareAtTime = globalClock.getFrameTime() taskMgr.add(self.__stareAt, self.__stareAtName) return def lerpLookAt(self, point, time = 1.0, blink = 0): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None lodNames = self.getLODNames() if lodNames: lodName = lodNames[0] else: return 0 head = self.getPart('head', lodName) startHpr = head.getHpr() startLpupil = self.__lpupil.getPos() startRpupil = self.__rpupil.getPos() self.__lookHeadAt(None, point, lod=lodName) self.__lookPupilsAt(None, point) endHpr = head.getHpr() endLpupil = self.__lpupil.getPos() * 0.5 endRpupil = self.__rpupil.getPos() * 0.5 head.setHpr(startHpr) self.__lpupil.setPos(startLpupil) self.__rpupil.setPos(startRpupil) if startHpr.almostEqual(endHpr, 10): return 0 if blink: self.blinkEyes() lookToTgt_TimeFraction = 0.2 lookToTgtTime = time * lookToTgt_TimeFraction returnToEyeCenterTime = time - lookToTgtTime - 0.5 origin = Point3(0, 0, 0) blendType = 'easeOut' self.lookAtTrack = Parallel(Sequence(LerpPosInterval(self.__lpupil, lookToTgtTime, endLpupil, blendType=blendType), Wait(0.5), LerpPosInterval(self.__lpupil, returnToEyeCenterTime, origin, blendType=blendType)), Sequence(LerpPosInterval(self.__rpupil, lookToTgtTime, endRpupil, blendType=blendType), Wait(0.5), LerpPosInterval(self.__rpupil, returnToEyeCenterTime, origin, blendType=blendType)), name=self.__stareAtName) for lodName in self.getLODNames(): head = self.getPart('head', lodName) self.lookAtTrack.append(LerpHprInterval(head, time, endHpr, blendType='easeInOut')) self.lookAtTrack.start() return 1 def stopStareAt(self): self.lerpLookAt(Vec3.forward()) def stopStareAtNow(self): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None if self.__lpupil and self.__rpupil: self.__setPupilDirection(0, 0) for lodName in self.getLODNames(): head = self.getPart('head', lodName) head.setHpr(0, 0, 0) def __lookAround(self, task): self.findSomethingToLookAt() t = self.randGen.random() * 4.0 + 3.0 taskMgr.doMethodLater(t, self.__lookAround, self.__lookName) return Task.done def startLookAround(self): taskMgr.remove(self.__lookName) t = self.randGen.random() * 5.0 + 2.0 taskMgr.doMethodLater(t, self.__lookAround, self.__lookName) def stopLookAround(self): taskMgr.remove(self.__lookName) self.stopStareAt() def stopLookAroundNow(self): taskMgr.remove(self.__lookName) self.stopStareAtNow() def enterEyelidsOff(self): return None def exitEyelidsOff(self): return None def enterEyelidsOpen(self): if not self.__eyes.isEmpty(): self.__eyes.setTexture(self.__eyesOpen, 1) if self.__eyelashOpen: self.__eyelashOpen.show() if self.__eyelashClosed: self.__eyelashClosed.hide() if self.__lod500Eyes: self.__lod500Eyes.setTexture(self.__eyesOpen, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(self.__eyesOpen, 1) if self.__lpupil: self.__lpupil.show() self.__rpupil.show() if self.__lod500lPupil: self.__lod500lPupil.show() self.__lod500rPupil.show() if self.__lod250lPupil: self.__lod250lPupil.show() self.__lod250rPupil.show() def exitEyelidsOpen(self): return None def enterEyelidsClosed(self): if not self.__eyes.isEmpty() and self.__eyesClosed: self.__eyes.setTexture(self.__eyesClosed, 1) if self.__eyelashOpen: self.__eyelashOpen.hide() if self.__eyelashClosed: self.__eyelashClosed.show() if self.__lod500Eyes: self.__lod500Eyes.setTexture(self.__eyesClosed, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(self.__eyesClosed, 1) if self.__lpupil: self.__lpupil.hide() self.__rpupil.hide() if self.__lod500lPupil: self.__lod500lPupil.hide() self.__lod500rPupil.hide() if self.__lod250lPupil: self.__lod250lPupil.hide() self.__lod250rPupil.hide() def exitEyelidsClosed(self): return None def enterEyelidsSurprised(self): if not self.__eyes.isEmpty() and ToonHead.EyesSurprised: self.__eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__eyelashOpen: self.__eyelashOpen.hide() if self.__eyelashClosed: self.__eyelashClosed.hide() if self.__lod500Eyes: self.__lod500Eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__muzzle: self.__muzzle.setTexture(ToonHead.MuzzleSurprised, 1) if self.__lpupil: self.__lpupil.show() self.__rpupil.show() if self.__lod500lPupil: self.__lod500lPupil.show() self.__lod500rPupil.show() if self.__lod250lPupil: self.__lod250lPupil.show() self.__lod250rPupil.show() def exitEyelidsSurprised(self): if self.__muzzle: self.__muzzle.setTexture(ToonHead.Muzzle, 1) def setupMuzzles(self, style): self.__muzzles = [] self.__surpriseMuzzles = [] self.__angryMuzzles = [] self.__sadMuzzles = [] self.__smileMuzzles = [] self.__laughMuzzles = [] def hideAddNonEmptyItemToList(item, list): if not item.isEmpty(): item.hide() list.append(item) def hideNonEmptyItem(item): if not item.isEmpty(): item.hide() if self.hasLOD(): for lodName in self.getLODNames(): animal = style.getAnimal() if animal != 'dog': muzzle = self.find('**/' + lodName + '/**/muzzle*neutral') else: muzzle = self.find('**/' + lodName + '/**/muzzle*') if lodName == '1000' or lodName == '500': filePrefix = DogMuzzleDict[style.head] muzzles = loader.loadModel('phase_3' + filePrefix + lodName) if base.config.GetBool('want-new-anims', 1): if not self.find('**/' + lodName + '/**/__Actor_head/def_head').isEmpty(): muzzles.reparentTo(self.find('**/' + lodName + '/**/__Actor_head/def_head')) else: muzzles.reparentTo(self.find('**/' + lodName + '/**/joint_toHead')) elif self.find('**/' + lodName + '/**/joint_toHead'): muzzles.reparentTo(self.find('**/' + lodName + '/**/joint_toHead')) surpriseMuzzle = self.find('**/' + lodName + '/**/muzzle*surprise') angryMuzzle = self.find('**/' + lodName + '/**/muzzle*angry') sadMuzzle = self.find('**/' + lodName + '/**/muzzle*sad') smileMuzzle = self.find('**/' + lodName + '/**/muzzle*smile') laughMuzzle = self.find('**/' + lodName + '/**/muzzle*laugh') self.__muzzles.append(muzzle) hideAddNonEmptyItemToList(surpriseMuzzle, self.__surpriseMuzzles) hideAddNonEmptyItemToList(angryMuzzle, self.__angryMuzzles) hideAddNonEmptyItemToList(sadMuzzle, self.__sadMuzzles) hideAddNonEmptyItemToList(smileMuzzle, self.__smileMuzzles) hideAddNonEmptyItemToList(laughMuzzle, self.__laughMuzzles) else: if style.getAnimal() != 'dog': muzzle = self.find('**/muzzle*neutral') else: muzzle = self.find('**/muzzle*') filePrefix = DogMuzzleDict[style.head] muzzles = loader.loadModel('phase_3' + filePrefix + '1000') if base.config.GetBool('want-new-anims', 1): if not self.find('**/def_head').isEmpty(): muzzles.reparentTo(self.find('**/def_head')) else: muzzles.reparentTo(self.find('**/joint_toHead')) else: muzzles.reparentTo(self.find('**/joint_toHead')) surpriseMuzzle = self.find('**/muzzle*surprise') angryMuzzle = self.find('**/muzzle*angry') sadMuzzle = self.find('**/muzzle*sad') smileMuzzle = self.find('**/muzzle*smile') laughMuzzle = self.find('**/muzzle*laugh') self.__muzzles.append(muzzle) hideAddNonEmptyItemToList(surpriseMuzzle, self.__surpriseMuzzles) hideAddNonEmptyItemToList(angryMuzzle, self.__angryMuzzles) hideAddNonEmptyItemToList(sadMuzzle, self.__sadMuzzles) hideAddNonEmptyItemToList(smileMuzzle, self.__smileMuzzles) hideAddNonEmptyItemToList(laughMuzzle, self.__laughMuzzles) def getMuzzles(self): return self.__muzzles def getSurpriseMuzzles(self): return self.__surpriseMuzzles def getAngryMuzzles(self): return self.__angryMuzzles def getSadMuzzles(self): return self.__sadMuzzles def getSmileMuzzles(self): return self.__smileMuzzles def getLaughMuzzles(self): return self.__laughMuzzles def showNormalMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__muzzles)): self.__muzzles[muzzleNum].show() def hideNormalMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__muzzles)): self.__muzzles[muzzleNum].hide() def showAngryMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__angryMuzzles)): self.__angryMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideAngryMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__angryMuzzles)): self.__angryMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSadMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__sadMuzzles)): self.__sadMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSadMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__sadMuzzles)): self.__sadMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSmileMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__smileMuzzles)): self.__smileMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSmileMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__smileMuzzles)): self.__smileMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showLaughMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__laughMuzzles)): self.__laughMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideLaughMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__laughMuzzles)): self.__laughMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSurpriseMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__surpriseMuzzles)): self.__surpriseMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSurpriseMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in range(len(self.__surpriseMuzzles)): self.__surpriseMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def isIgnoreCheesyEffect(self): if hasattr(self, 'savedCheesyEffect'): if self.savedCheesyEffect == 10 or self.savedCheesyEffect == 11 or self.savedCheesyEffect == 12 or self.savedCheesyEffect == 13 or self.savedCheesyEffect == 14: return True return False
class Walk(StateData): notify = directNotify.newCategory("Walk") def __init__(self, doneEvent): StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('Walk', [ State('off', self.enterOff, self.exitOff, ['walking', 'deadWalking']), State('walking', self.enterWalking, self.exitWalking), State('deadWalking', self.enterDeadWalking, self.exitDeadWalking)], 'off', 'off') self.fsm.enterInitialState() def load(self): pass def unload(self): del self.fsm def enter(self): base.localAvatar.startPosHprBroadcast() base.localAvatar.d_broadcastPositionNow() base.localAvatar.startBlink() base.localAvatar.attachCamera() base.localAvatar.startSmartCamera() base.localAvatar.collisionsOn() base.localAvatar.enableAvatarControls() def exit(self): base.localAvatar.lastState = None self.fsm.request('off') base.localAvatar.disableAvatarControls() base.localAvatar.detachCamera() base.localAvatar.stopSmartCamera() base.localAvatar.stopPosHprBroadcast() base.localAvatar.stopBlink() base.localAvatar.collisionsOff() base.localAvatar.controlManager.placeOnFloor() def enterOff(self): pass def exitOff(self): pass def enterWalking(self): if base.localAvatar.getHealth() > 0: base.localAvatar.startTrackAnimToSpeed() base.localAvatar.setWalkSpeedNormal() else: self.fsm.request('deadWalking') def exitWalking(self): base.localAvatar.stopTrackAnimToSpeed() def enterDeadWalking(self): base.localAvatar.startTrackAnimToSpeed() base.localAvatar.setWalkSpeedSlow() base.taskMgr.add(self.__watchForPositiveHP, base.localAvatar.uniqueName('watchforPositiveHP')) def __watchForPositiveHP(self, task): if base.localAvatar.getHealth() > 0: self.fsm.request('walking') return task.done return task.cont def exitDeadWalking(self): base.taskMgr.remove(base.localAvatar.uniqueName('watchforPositiveHP')) base.localAvatar.stopTrackAnimToSpeed()
class DynamicHuman(HumanBase.HumanBase, Biped.Biped): notify = DirectNotifyGlobal.directNotify.newCategory('Human') def __init__(self, other = None): Biped.Biped.__init__(self, other, HumanAnimationMixer) self.model = None self.zombie = False self.crazyColorSkin = False self.crazyColorSkinIndex = 0 self.flattenPending = None if __dev__: self.optimizeLOD = base.config.GetBool('optimize-avatar-lod', 1) else: self.optimizeLOD = 0 self.master = 0 self.loaded = 0 self.playingRate = None self.shadowFileName = 'models/misc/drop_shadow' self.setFont(PiratesGlobals.getInterfaceFont()) self._DynamicHuman__blinkName = 'blink-' + str(self.this) self.eyeLids = None self.eyeBalls = None self.eyeIris = None self.reducedAnimList = None self.headNode = None self.extraNode = None self.scaleNode = None self.rootNode = None self.floorOffsetZ = 0.0 self.headFudgeHpr = Vec3(0, 0, 0) self.randGen = random.Random() self.randGen.seed(random.random()) self.eyeFSM = ClassicFSM('eyeFSM', [ State('off', self.enterEyeFSMOff, self.exitEyeFSMOff, [ 'open', 'closed']), State('open', self.enterEyeFSMOpen, self.exitEyeFSMOpen, [ 'closed', 'off']), State('closed', self.enterEyeFSMClosed, self.exitEyeFSMClosed, [ 'open', 'off'])], 'off', 'off') self.eyeFSM.enterInitialState() self.isPaid = True if other != None: self.copyHuman(other) def removeCopiedNodes(self): self.dropShadow = self.find('**/drop_shadow*') if not self.dropShadow.isEmpty(): self.deleteDropShadow() def flattenHuman(self): self.deleteNametag3d() self.getWeaponJoints() def _DynamicHuman__doneFlattenHuman(self, models): self.flattenPending = None self.getWeaponJoints() def copyHuman(self, other): self.gender = other.gender self.loaded = other.loaded self.type = other.type self.loadAnimatedHead = other.loadAnimatedHead self.flattenHuman() self.model = None def delete(self): self.Human_deleted = 1 taskMgr.remove(self._DynamicHuman__blinkName) if self.dropShadow and not self.dropShadow.isEmpty(): self.deleteDropShadow() del self.eyeFSM self.controlShapes = None self.sliderNames = None if self.model: self.model.delete() del self.model Biped.Biped.delete(self) def isDeleted(self): try: if self.Human_deleted == 1: return True except: return False def setupExtraNodes(self): idx = 0 if self.gender == 'f': idx = 1 jointName = 'def_head01' jointNameExtra = 'def_extra_jt' jointNameScale = 'def_scale_jt' lods = self.getLODNames() self.headNode = self.controlJoint(None, 'legs', jointName, lods[0]) self.extraNode = self.controlJoint(None, 'legs', jointNameExtra, lods[0]) self.scaleNode = self.controlJoint(None, 'legs', jointNameScale, lods[0]) self.rootNode = self.getLOD('2000').find('**/dx_root') self.floorOffsetZ = self.rootNode.getZ() for lod in lods[1:]: self.controlJoint(self.headNode, 'legs', jointName, lod) self.controlJoint(self.extraNode, 'legs', jointNameExtra, lod) self.controlJoint(self.scaleNode, 'legs', jointNameScale, lod) exposedHeadJoint = self.getLOD(lod).find('**/def_head01') if not exposedHeadJoint.isEmpty(): exposedHeadJoint.removeNode() continue self.headNode.setScale(HeadScales[idx][self.style.getBodyShape()]) self.setGlobalScale(self.calcBodyScale()) def undoExtraNodes(self): jointNameExtra = 'def_extra_jt' jointNameScale = 'def_scale_jt' joints = self.findAllMatches('**/*' + jointNameExtra) if not joints.isEmpty(): joints.detach() joints.clear() if self.headNode: self.headNode.removeNode() self.headNode = None self.extraNode.removeNode() self.extraNode = None joints = self.findAllMatches('**/*' + jointNameScale) if not joints.isEmpty(): joints.detach() joints.clear() if self.scaleNode: self.scaleNode.removeNode() self.scaleNode = None self.rootNode = None def fixEyes(self): self.eyeLids = { } self.eyeBalls = { } self.eyeIris = { } for lodName in self.getLODNames(): geom = self.getPart('head', lodName) self.eyeLids[lodName] = geom.findAllMatches('**/*eyelid*') self.eyeBalls[lodName] = geom.findAllMatches('**/eye_ball*') self.eyeIris[lodName] = geom.findAllMatches('**/eye_iris*') self.eyeLids[lodName].stash() self.eyeBalls[lodName].unstash() self.eyeIris[lodName].unstash() def generateFaceTexture(self): faceTextureIdx = self.style.head.texture if self.gender == 'f': face_textures = PirateFemale.face_textures else: face_textures = PirateMale.face_textures tex_name = self.getTrySafe(face_textures, faceTextureIdx) if tex_name != None: tex = self.model.faceTextures.findTexture(tex_name) if tex == None: return None else: return None for lodName in self.getLODNames(): self.findAllMatches('**/body_master_face').setTexture(tex, 1) def generateSkinColor(self): skinColor = self.style.getSkinColor() self.model.faces[0].setColorScale(skinColor) if self.model.newAvatars: self.model.currentBody.setColorScale(skinColor) else: numPaths = self.model.body.getNumPaths() if self.zombie: self.model.body.setColorScale(Vec4(1, 1, 1, 1)) else: self.model.body.setColorScale(skinColor) def generateSkinTexture(self): bodyTextureIdx = self.style.body.skin if self.zombie: if self.gender == 'f': bodyTextureIdx = PirateFemale.ZOMB_BODY_TEXTURE else: bodyTextureIdx = PirateMale.ZOMB_BODY_TEXTURE if self.gender == 'f': body_textures = PirateFemale.body_textures[self.style.body.shape] else: body_textures = PirateMale.body_textures[self.style.body.shape] tex_name = self.getTrySafe(body_textures, bodyTextureIdx) if tex_name != None: tex = self.model.bodyTextures.findTexture(tex_name) else: return None for parts in self.model.bodys: parts.setTexture(tex, 1) def generateHairColor(self, colorName = None, colorModel = None): self.model.setHairBaseColor() def getTrySafe(self, list, idx): try: if type(idx) == str: lookup = idx.split('_cut')[0] else: lookup = idx return list[lookup] except: return None def generateEyesTexture(self): eyesTextureIdx = self.style.head.eyes.color if self.gender == 'f': eye_iris_textures = PirateFemale.eye_iris_textures else: eye_iris_textures = PirateMale.eye_iris_textures tex_name = self.getTrySafe(eye_iris_textures, eyesTextureIdx) if tex_name != None: tex = self.eyeIrisTextures.findTexture(tex_name) else: return None self.model.irises.setTexture(tex, 1) def generateHatColor(self): style = self.style if self.zombie: style = self.model.dnaZomb hatColor = style.lookupHatColor() geom = self.getGeomNode() geom.findAllMatches('**/hat_band*').setColorScale(hatColor) def generateClothesColor(self): style = self.style if self.zombie: style = self.model.dnaZomb clothesTopColor = style.lookupClothesTopColor() clothesBotColor = style.lookupClothesBotColor() geom = self.getGeomNode() geom.findAllMatches('**/clothing_layer1_shirt*').setColorScale(clothesTopColor[0]) geom.findAllMatches('**/clothing_layer2_vest*').setColorScale(clothesTopColor[1]) geom.findAllMatches('**/clothing_layer3_coat*').setColorScale(clothesTopColor[2]) geom.findAllMatches('**/clothing_layer1_pant*').setColorScale(clothesBotColor[0]) geom.findAllMatches('**/clothing_layer2_belt*').setColorScale(clothesBotColor[1]) geom.findAllMatches('**/clothing_layer1_shoe*').setColorScale(clothesBotColor[2]) def generateColor(self): self.generateSkinColor() self.generateHairColor() self.generateHatColor() def makeAnimDict(self, gender, animNames): self.animDict = [] for currAnim in animNames: anim = animNames.get(currAnim) for currAnimName in anim: self.animTable.append([ currAnimName, currAnimName]) self.reducedAnimList = self.animDict def forceLoadAnimDict(self): for anim in self.animDict: self.getAnimControls(anim[0]) def createAnimDict(self, customList = None): if self.gender == 'f': filePrefix = 'models/char/f' genderPrefix = 'f' else: filePrefix = 'models/char/m' genderPrefix = 'm' filePrefix += 'p' animList = self.reducedAnimList if animList is None: animList = AnimListDict[self.type] AnimDict.clear() for anim in animList: animSuffix = '' for customAnim in CustomAnimDict[genderPrefix + self.type]: if anim[0] == customAnim: animSuffix = '_' + genderPrefix + NewModelDict.get(self.type) break continue AnimDict[anim[0]] = filePrefix + '_' + anim[1] + animSuffix if self.reducedAnimList is None: AnimDict.pop('intro') return filePrefix def generateBody(self, copy = 1): filePrefix = self.createAnimDict() lodString = '2000' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '2000', copy) self.loadAnims(AnimDict, 'modelRoot', 'all') if loader.loadModel(filePrefix + '_' + '1000', allowInstance = True) != None: lodString = '1000' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '1000', copy) if loader.loadModel(filePrefix + '_' + '500', allowInstance = True) != None: lodString = '500' self.loadModel(filePrefix + '_' + lodString, 'modelRoot', '500', copy) self.makeSubpart('head', [ 'zz_head01'], []) self.makeSubpart('torso', [ 'zz_spine01'], [ 'zz_head01']) self.makeSubpart('legs', [ 'dx_root'], [ 'zz_spine01']) self.setSubpartsComplete(True) self.getWeaponJoints() self.eyeIrisTextures = loader.loadModel('models/misc/eye_iris.bam') def refreshBody(self): if self.style.getGender() == 'f': gender = 1 cjs = FemaleBodyShapeControlJoints matrix = FemaleBodyShapeControlJointMatrix else: gender = 0 cjs = MaleBodyShapeControlJoints matrix = MaleBodyShapeControlJointMatrix type = self.style.getBodyShape() filePrefix = self.createAnimDict() self.loadAnims(AnimDict, 'modelRoot', 'all') for jointName in cjs: joint = self.find('**/*' + jointName) vector = matrix[jointName][type] if jointName.find('def') != -1: joint.setScale(vector) continue joint.setPos(vector) self.headNode.setScale(HeadScales[gender][self.style.getBodyShape()]) self.setGlobalScale(self.calcBodyScale()) self.createAnimDict() self.stop(self.getCurrentAnim()) self.loop(self.getCurrentAnim()) def setLODs(self): self.setLODNode() avatarDetail = base.config.GetString('avatar-detail', 'high') if avatarDetail == 'high': dist = [ 0, 20, 80, 280] elif avatarDetail == 'med': dist = [ 0, 10, 40, 280] elif avatarDetail == 'low': dist = [ 0, 5, 20, 280] else: raise StandardError, 'Invalid avatar-detail: %s' % avatarDetail self.addLOD(2000, dist[1], dist[0]) self.addLOD(1000, dist[2], dist[1]) self.addLOD(500, dist[3], dist[2]) if self.optimizeLOD: lowLOD = self.getLOD('500') lowLOD.setTextureOff(1000) lowLOD.setTransparency(0, 1000) self.getLODNode().setCenter(Point3(0, 0, 5)) def showLOD(self, lodName): if not self.model.loaded: self.model.setupHead(lodName) self.model.setupBody(lodName) self.model.setupClothing(lodName) if self.master: self.model.setupSelectionChoices('NPC') self.model.loaded = 1 self.model.setFromDNA() self.generateEyesTexture() if self.optimizeLOD: self.optimizeLowLOD() self.generateColor() def loadHuman(self, gender = 'm', other = None): if other: pirate = other pirate.style = self.style else: pirate = self pirate.gender = gender if self.loaded: return None if pirate.gender == 'f': pirate.type = BodyDefs.femaleFrames[pirate.style.getBodyShape()] controlShapes = PirateFemale.ControlShapes sliderNames = PirateFemale.SliderNames else: pirate.type = BodyDefs.maleFrames[pirate.style.getBodyShape()] controlShapes = PirateMale.ControlShapes sliderNames = PirateMale.SliderNames if not pirate.loaded: pirate.setLODs() pirate.loadAnimatedHead = True pirate.generateBody() if pirate.gender == 'f': pirate.model = PirateFemale.PirateFemale(pirate, pirate.style) self.pirateFemale = PirateFemale.PirateFemale(pirate, pirate.style) else: pirate.model = PirateMale.PirateMale(pirate, pirate.style) self.pirateMale = PirateMale.PirateMale(pirate, pirate.style) if base.config.GetBool('debug-dynamic-human', 0): pirate.model.newAvatars = True else: pirate.model.newAvatars = False pirate.faceAwayFromViewer() pirate.fixEyes() else: pirate.model.dna = pirate.style pirate.reducedAnimList = self.reducedAnimList pirate.createAnimDict() pirate.loadAnims(AnimDict, 'modelRoot', 'all') self.lods = pirate.getLODNames() if pirate.gender == 'f': self.headFudgeHpr = Vec3(0, 0, 0) idx = 1 else: self.headFudgeHpr = Vec3(0, 0, 0) idx = 0 pirate.zombie = self.zombie pirate.showLOD(2000) pirate.loaded = 1 self.model = pirate.model if pirate.zombie: pirate.showZombie() else: pirate.showNormal() if hasattr(self, 'motionFSM'): self.motionFSM.setAvatar(self) self.controlShapes = controlShapes self.sliderNames = sliderNames if other: self.copyActor(other) self.fixEyes() self.copyHuman(other) self.undoExtraNodes() self.setupExtraNodes() self.applyBodyShaper() self.applyHeadShaper() if other: pirate.zombie = 0 pirate.showNormal() pirate.unloadAnims(AnimDict, None, None) pirate.removeAnimControlDict() pirate.reducedAnimList = None self.initializeMiscNodes() self.startBlink() def initializeMiscNodes(self): self.initializeNametag3d() self.initializeDropShadow() if self.getLOD('2000') == None: return None exposedHeadJoint = self.getLOD('2000').find('**/def_head01') if not exposedHeadJoint.isEmpty(): idx = 0 if self.gender == 'f': idx = 1 exposedHeadJoint.setScale(1) self.headNode.reparentTo(exposedHeadJoint) self.headNode.setScale(HeadScales[idx][self.style.getBodyShape()]) def undoControlJoints(self): self.getGeomNode().getParent().findAllMatches('def_*').detach() self.getGeomNode().getParent().findAllMatches('trs_*').detach() self.findAllMatches('def_*').detach() self.findAllMatches('trs_*').detach() def cleanupHuman(self, gender = 'm'): self.eyeFSM.request('off') self.undoExtraNodes() self.undoControlJoints() self.eyeLids = { } self.eyeBalls = { } self.eyeIris = { } self.flush() self.loaded = 0 self.master = 0 def generateHuman(self, gender = 'm', others = None): other = None if others: if gender == 'f': other = others[1] else: other = others[0] if other and not (other.master) and other.loaded: other.cleanupHuman() elif self.loaded: self.cleanupHuman() self.loadHuman(self.style.gender, other) if self.isLocal(): self.renderReflection = True self.setRenderReflection() self.disableMixing() self.enableMixing() generateHuman = quickProfile('loadHuman')(generateHuman) def getShadowJoint(self): return self def getNametagJoints(self): joints = [] for lodName in self.getLODNames(): bundle = self.getPartBundle('legs', lodName) joint = bundle.findChild('name_tag') if joint: joints.append(joint) continue return joints def _DynamicHuman__blinkOpenEyes(self, task): if self.eyeFSM.getCurrentState().getName() == 'closed': self.eyeFSM.request('open') r = self.randGen.random() if r < 0.10000000000000001: t = 0.20000000000000001 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self._DynamicHuman__blinkCloseEyes, self._DynamicHuman__blinkName) return Task.done def _DynamicHuman__blinkCloseEyes(self, task): if self.eyeFSM.getCurrentState().getName() != 'open': taskMgr.doMethodLater(4.0, self._DynamicHuman__blinkCloseEyes, self._DynamicHuman__blinkName) else: self.eyeFSM.request('closed') taskMgr.doMethodLater(0.125, self._DynamicHuman__blinkOpenEyes, self._DynamicHuman__blinkName) return Task.done def startBlink(self): taskMgr.remove(self._DynamicHuman__blinkName) if self.eyeLids: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self._DynamicHuman__blinkCloseEyes, self._DynamicHuman__blinkName) def stopBlink(self): taskMgr.remove(self._DynamicHuman__blinkName) if self.eyeLids: self.eyeFSM.request('open') def closeEyes(self): self.eyeFSM.request('closed') def openEyes(self): self.eyeFSM.request('open') def enterEyeFSMOff(self): pass def exitEyeFSMOff(self): pass def enterEyeFSMOpen(self): for lodName in self.getLODNames(): if not self.eyeLids[lodName].isEmpty(): self.eyeLids[lodName].hide() self.eyeBalls[lodName].show() self.eyeIris[lodName].show() continue def exitEyeFSMOpen(self): pass def enterEyeFSMClosed(self): return None for lodName in self.getLODNames(): if not self.eyeLids[lodName].isEmpty(): self.eyeLids[lodName].show() self.eyeBalls[lodName].hide() self.eyeIris[lodName].hide() continue def exitEyeFSMClosed(self): pass def setControlValue(self, r, name): if self.style.getGender() == 'f': matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix else: matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix shapes = self.controlShapes ctl = shapes[name] slider = ctl[0] if r < 0.0: if len(ctl) > 1: slider = ctl[1] for i in range(0, len(slider)): jointName = slider[i][0] jointCtls = self.findAllMatches(jointName) posI = matrixI[jointName][0] hprI = matrixI[jointName][1] sclI = matrixI[jointName][2] posF = VBase3(posI[0], posI[1], posI[2]) hprF = VBase3(hprI[0], hprI[1], hprI[2]) sclF = VBase3(sclI[0], sclI[1], sclI[2]) self.notify.debug('scv: %s initial %s' % (jointName, posI)) dr = slider[i][4] * r ctl[0][i][5] = dr posDelta = VBase3(0, 0, 0) hprDelta = VBase3(0, 0, 0) sclDelta = VBase3(0, 0, 0) for sliderIdx in xrange(0, len(matrixF[jointName])): sliderName = matrixF[jointName][sliderIdx] jointSet = shapes[sliderName][0] for jointIdx in xrange(0, len(jointSet)): if jointSet[jointIdx][0] == jointName: if jointSet[jointIdx][1] == TX: posDelta.setX(posDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == TY: posDelta.setY(posDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == TZ: posDelta.setZ(posDelta.getZ() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RX: hprDelta.setX(hprDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RY: hprDelta.setY(hprDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == RZ: hprDelta.setZ(hprDelta.getZ() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SX: if r < 0.0: sclDelta.setX(sclDelta.getX() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setX(sclDelta.getX() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SY: if r < 0.0: sclDelta.setY(sclDelta.getY() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setY(sclDelta.getY() + jointSet[jointIdx][5]) elif jointSet[jointIdx][1] == SZ: if r < 0.0: sclDelta.setZ(sclDelta.getZ() + jointSet[jointIdx][5] / jointSet[jointIdx][2]) else: sclDelta.setZ(sclDelta.getZ() + jointSet[jointIdx][5]) else: self.notify.warning('scv:wrong element = %s' % jointSet[jointIdx][1]) jointSet[jointIdx][1] == TX self.notify.debug('scv: %s composite posDelta = %s' % (jointName, posDelta)) posF.setX(posI[0] + posDelta[0]) posF.setY(posI[1] + posDelta[1]) posF.setZ(posI[2] + posDelta[2]) self.notify.debug('scv: %s final posDelta%s' % (jointName, posF)) self.notify.debug('scv: %s composite hprDelta = %s' % (jointName, hprDelta)) hprF.setX(hprI[0] + hprDelta[0]) hprF.setY(hprI[1] + hprDelta[1]) hprF.setZ(hprI[2] + hprDelta[2]) self.notify.debug('scv: %s final hprDelta%s' % (jointName, hprF)) self.notify.debug('scv: %s composite sclDelta = %s' % (jointName, sclDelta)) sclF.setX(sclI[0] + sclDelta[0]) sclF.setY(sclI[1] + sclDelta[1]) sclF.setZ(sclI[2] + sclDelta[2]) self.notify.debug('scv: %s final sclDelta%s' % (jointName, sclF)) for j in range(0, jointCtls.getNumPaths()): jointCtl = jointCtls[j] jointCtl.setPosHprScale(posF, hprF, sclF) def applyBodyShaper(self): if self.style.getGender() == 'f': cjs = FemaleBodyShapeControlJoints matrix = FemaleBodyShapeControlJointMatrix else: cjs = MaleBodyShapeControlJoints matrix = MaleBodyShapeControlJointMatrix type = self.style.getBodyShape() for jointName in cjs: for lodName in self.getLODNames(): if lodName == '2000': joint = self.controlJoint(None, 'legs', jointName, lodName) continue joint = self.controlJoint(joint, 'legs', jointName, lodName) joint = self.find('**/*' + jointName) vector = matrix[jointName][type] if jointName.find('def') != -1: joint.setScale(vector) continue joint.setPos(vector) def undoBodyShaper(self): if self.style.getGender() == 'f': cjs = FemaleBodyShapeControlJoints else: cjs = MaleBodyShapeControlJoints def applyHeadShaper(self): self.createControlJoints() self.initHeadControlShapes() self.setHeadControlShapeValues() def undoHeadShaper(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints else: cjs = MaleHeadShapeControlJoints def createControlJoints(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints else: cjs = MaleHeadShapeControlJoints for jointName in cjs: for lodName in self.getLODNames(): if lodName == '2000': joint = self.controlJoint(None, 'legs', jointName, lodName) continue if lodName == '1000': continue continue if lodName == '500': continue continue def initHeadControlShapes(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix else: cjs = MaleHeadShapeControlJoints matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix if len(matrixF['initialized']) > 0: return None initializedMatrixI = len(matrixI['initialized']) initializedMatrixF = len(matrixF['initialized']) for jointName in cjs: transform = TransformState.makeMat(self.getJointTransform('legs', jointName, '2000')) pos = Vec3(transform.getPos()) hpr = Vec3(transform.getHpr()) scale = Vec3(transform.getScale()) matrixI[jointName].append(pos) matrixI[jointName].append(hpr) matrixI[jointName].append(scale) matrixI['initialized'].append('initialized') shapes = self.controlShapes names = self.sliderNames for i in xrange(0, len(shapes)): slider = shapes[names[i]] for k in xrange(0, len(slider[0])): slider[0][k][4] = slider[0][k][2] if len(slider) > 1: slider[1][k][4] = slider[1][k][2] continue for i in xrange(0, len(shapes)): slider = shapes[names[i]] for k in xrange(0, len(slider[0])): jointCtl = slider[0][k] jointName = jointCtl[0] matrixF[jointName].append(names[i]) pos = matrixI[jointName][0] hpr = matrixI[jointName][1] scl = matrixI[jointName][2] if jointCtl[1] < 3: posDelta = jointCtl[4] - pos[jointCtl[1]] jointCtl[4] = posDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = posDelta if len(slider) > 1: if jointCtl[1] > 2 and jointCtl[1] < 6: hprDelta = jointCtl[4] - hpr[jointCtl[1] - 3] jointCtl[4] = hprDelta if len(slider) > 1: jointCtl = slider[1][k] jointCtl[4] = hprDelta #if len(slider) > 1: #sclDelta = jointCtl[4] - scl[jointCtl[1] - 6] #jointCtl[4] = sclDelta #if len(slider) > 1: # jointCtl = slider[1][k] # jointCtl[4] = sclDelta matrixF['initialized'].append('initialized') def setHeadControlShapeValues_old(self): value = self.style.getHeadSize() mappedValue = 0.90000000000000002 + (1 + value) * 0.10000000000000001 self.extraNode.setScale(2 - mappedValue, mappedValue, 1) self.setControlValue(self.style.getHeadWidth(), 'headWidth') self.setControlValue(self.style.getHeadHeight(), 'headHeight') self.setControlValue(self.style.getHeadRoundness(), 'headRoundness') self.setControlValue(self.style.getJawWidth(), 'jawWidth') self.setControlValue(self.style.getJawAngle(), 'jawChinAngle') self.setControlValue(self.style.getJawChinSize(), 'jawChinSize') self.setControlValue(self.style.getJawLength(), 'jawLength') self.setControlValue(self.style.getMouthWidth(), 'mouthWidth') self.setControlValue(self.style.getMouthLipThickness(), 'mouthLipThickness') self.setControlValue(self.style.getCheekFat(), 'cheekFat') self.setControlValue(self.style.getBrowProtruding(), 'browProtruding') self.setControlValue(self.style.getEyeCorner(), 'eyeCorner') self.setControlValue(self.style.getEyeOpeningSize(), 'eyeOpeningSize') self.setControlValue(self.style.getEyeBulge(), 'eyeSpacing') self.setControlValue(self.style.getNoseBridgeWidth(), 'noseBridgeWidth') self.setControlValue(self.style.getNoseNostrilWidth(), 'noseNostrilWidth') self.setControlValue(self.style.getNoseLength(), 'noseLength') self.setControlValue(self.style.getNoseBump(), 'noseBump') self.setControlValue(self.style.getNoseNostrilHeight(), 'noseNostrilHeight') self.setControlValue(self.style.getNoseNostrilAngle(), 'noseNostrilAngle') self.setControlValue(self.style.getNoseBridgeBroke(), 'noseBridgeBroke') self.setControlValue(self.style.getNoseNostrilBroke(), 'noseNostrilBroke') self.setControlValue(self.style.getEarScale(), 'earScale') self.setControlValue(self.style.getEarFlapAngle(), 'earFlap') self.setControlValue(self.style.getEarPosition(), 'earPosition') def getGlobalScale(self): return self.scaleNode.getScale() def setGlobalScale(self, scale): self.scaleNode.setScale(scale) self.scaleNode.setZ(-(self.floorOffsetZ * (1 - scale))) def calcBodyScale(self): idx = 0 if self.gender == 'f': idx = 1 mappedValue = (0.80000000000000004 + (1 + self.style.getBodyHeight()) * 0.20000000000000001) * BodyScales[idx][self.style.getBodyShape()] return mappedValue def showZombie(self): self.model.irises.stash() self.model.faces[0].stash() self.model.faceZomb.unstash() self.generateSkinTexture() def showNormal(self): self.model.irises.unstash() self.model.faces[0].unstash() self.model.faceZomb.stash() self.generateSkinTexture() def takeAwayTexture(self, geoms, omitFace = False): emptyRenderState = RenderState.makeEmpty() eyeIrisColor = VBase4(0, 0, 0, 1) for i in range(0, geoms.getNumPaths()): element = geoms[i] if 'eye_iris' in element.getName(): element.setColorScale(eyeIrisColor) elif omitFace and 'master_face' in element.getName(): continue element.setTextureOff() geom = element.node() for j in range(0, geom.getNumGeoms()): geom.setGeomState(j, emptyRenderState) def optimizeMedLOD(self): medLOD = self.getLOD('1000') geoms = medLOD.findAllMatches('**/teeth*') geoms.stash() self.medSkinGone = False geoms = medLOD.find('**/body_forearm*') if geoms.isEmpty(): self.medSkinGone = True geoms = medLOD.findAllMatches('**/body_*') self.takeAwayTexture(geoms, True) geoms = medLOD.findAllMatches('**/hair_*') self.takeAwayTexture(geoms) if self.gender != 'f': geoms = medLOD.findAllMatches('**/beard_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/mustache_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/eye_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/clothing_layer2_belt_*') self.takeAwayTexture(geoms) geoms = medLOD.findAllMatches('**/clothing_layer1_shoe_*') self.takeAwayTexture(geoms) def optimizeLowLOD(self): lowLOD = self.getLOD('500') geoms = lowLOD.findAllMatches('**/teeth*') geoms.stash() geoms = lowLOD.findAllMatches('**/+GeomNode') self.takeAwayTexture(geoms) def setHeadControlShapeValues(self): value = self.style.getHeadSize() mappedValue = 0.90000000000000002 + (1 + value) * 0.10000000000000001 self.extraNode.setScale(2 - mappedValue, mappedValue, 1) self.setControlValue_new(self.style.getHeadWidth(), 'headWidth') self.setControlValue_new(self.style.getHeadHeight(), 'headHeight') self.setControlValue_new(self.style.getHeadRoundness(), 'headRoundness') self.setControlValue_new(self.style.getJawWidth(), 'jawWidth') self.setControlValue_new(self.style.getJawAngle(), 'jawChinAngle') self.setControlValue_new(self.style.getJawChinSize(), 'jawChinSize') self.setControlValue_new(self.style.getJawLength(), 'jawLength') self.setControlValue_new(self.style.getMouthWidth(), 'mouthWidth') self.setControlValue_new(self.style.getMouthLipThickness(), 'mouthLipThickness') self.setControlValue_new(self.style.getCheekFat(), 'cheekFat') self.setControlValue_new(self.style.getBrowProtruding(), 'browProtruding') self.setControlValue_new(self.style.getEyeCorner(), 'eyeCorner') self.setControlValue_new(self.style.getEyeOpeningSize(), 'eyeOpeningSize') self.setControlValue_new(self.style.getEyeBulge(), 'eyeSpacing') self.setControlValue_new(self.style.getNoseBridgeWidth(), 'noseBridgeWidth') self.setControlValue_new(self.style.getNoseNostrilWidth(), 'noseNostrilWidth') self.setControlValue_new(self.style.getNoseLength(), 'noseLength') self.setControlValue_new(self.style.getNoseBump(), 'noseBump') self.setControlValue_new(self.style.getNoseNostrilHeight(), 'noseNostrilHeight') self.setControlValue_new(self.style.getNoseNostrilAngle(), 'noseNostrilAngle') self.setControlValue_new(self.style.getNoseBridgeBroke(), 'noseBridgeBroke') self.setControlValue_new(self.style.getNoseNostrilBroke(), 'noseNostrilBroke') self.setControlValue_new(self.style.getEarScale(), 'earScale') self.setControlValue_new(self.style.getEarFlapAngle(), 'earFlap') self.setControlValue_new(self.style.getEarPosition(), 'earPosition') self.postProcess_setHeadControlShapeValues() def setControlValue_new(self, r, name): ctl = self.controlShapes[name] zeroindex = ctl[0] sliders = zeroindex if r < 0.0: if len(ctl) > 1: sliders = ctl[1] for i in range(0, len(sliders)): zeroindex[i][5] = sliders[i][4] * r def postProcess_setHeadControlShapeValues(self): if self.style.getGender() == 'f': cjs = FemaleHeadShapeControlJoints matrixF = FemaleHeadShapeControlJointMatrix matrixI = FemaleHeadShapeInitialControlJointMatrix else: cjs = MaleHeadShapeControlJoints matrixF = MaleHeadShapeControlJointMatrix matrixI = MaleHeadShapeInitialControlJointMatrix posDelta = VBase3() hprDelta = VBase3() sclDelta = VBase3() fdict2 = { 0: posDelta.addX, 1: posDelta.addY, 2: posDelta.addZ, 3: hprDelta.addX, 4: hprDelta.addY, 5: hprDelta.addZ, 6: sclDelta.addX, 7: sclDelta.addY, 8: sclDelta.addZ } for jointName in cjs: posDelta.assign(matrixI[jointName][0]) hprDelta.assign(matrixI[jointName][1]) sclDelta.assign(matrixI[jointName][2]) for sliderIdx in xrange(0, len(matrixF[jointName])): sliderName = matrixF[jointName][sliderIdx] jointSet = self.controlShapes[sliderName][0] for sliderJoint in jointSet: if sliderJoint[0] == jointName: fdict2[sliderJoint[1]](sliderJoint[5]) continue self.find(jointName).setPosHprScale(posDelta, hprDelta, sclDelta)
class DistributedMinigame(DistributedObject.DistributedObject, Timer.Timer): def __init__(self, cr): try: self.DistributedMinigame_initialized return except: self.DistributedMinigame_initialized = 1 DistributedObject.DistributedObject.__init__(self, cr) Timer.Timer.__init__(self) self.headPanels = HeadPanels() self.finalScoreUI = FinalScoreGUI() self.fsm = ClassicFSM('DistributedMinigame', [State('start', self.enterStart, self.exitStart, ['waitForOthers']), State('waitForOthers', self.enterWaitForOthers, self.exitWaitForOthers, ['play']), State('play', self.enterPlay, self.exitPlay, ['gameOver']), State('gameOver', self.enterGameOver, self.exitGameOver, ['off']), State('off', self.enterOff, self.exitOff)], 'off', 'off') self.fsm.enterInitialState() self.cr = cr self.localAv = base.localAvatar self.localAvId = self.localAv.doId self.musicPath = 'phase_4/audio/bgm/trolley_song.mid' self.winSfx = base.loadSfx('phase_4/audio/sfx/MG_win.mp3') self.loseSfx = base.loadSfx('phase_4/audio/sfx/MG_lose.mp3') self.prizeHigh = base.loadSfx('phase_6/audio/sfx/KART_Applause_1.mp3') self.prizeLow = base.loadSfx('phase_6/audio/sfx/KART_Applause_4.mp3') self.music = None self.description = '' self.descDialog = None self.winnerPrize = 0 self.loserPrize = 0 self.winnerMsg = 'Winner!\nYou have earned: %s' self.loserMsg = 'Loser!\nYou have earned: %s' self.allWinnerMsgs = ['Nice try!\nYou have earned: %s', 'Good job!\nYou have earned: %s', 'Way to go!\nYou have earned: %s', 'Awesome!\nYou have earned: %s'] self.timer = None self.timeLbl = None return def enterFinalScores(self): self.finalScoreUI.load() self.finalScoreUI.showFinalScores() def exitFinalScores(self): self.finalScoreUI.hideFinalScores() self.finalScoreUI.unload() def finalScores(self, avIdList, scoreList): self.finalScoreUI.handleFinalScores(avIdList, scoreList) def generateHeadPanel(self, gender, head, headtype, color, doId, name): self.headPanels.generate(gender, head, headtype, color, doId, name) def updateHeadPanelValue(self, doId, direction): self.headPanels.updateValue(doId, direction) def setTimerTime(self, time): self.setTime(time) def createTimer(self): Timer.Timer.load(self) def deleteTimer(self): Timer.Timer.unload(self) def setDescription(self, desc): self.description = desc def getDescription(self): return self.description def enterStart(self): self.descDialog = GlobalDialog(style=3, message=self.getDescription(), doneEvent='gameDescAck') self.acceptOnce('gameDescAck', self.handleDescAck) def handleDescAck(self): self.d_ready() self.fsm.request('waitForOthers') def exitStart(self): self.ignore('gameDescAck') self.descDialog.cleanup() del self.descDialog def enterWaitForOthers(self): self.waitLbl = DirectLabel(text='Waiting for other players...', relief=None, text_fg=(1, 1, 1, 1), text_scale=0.08, text_shadow=(0, 0, 0, 1)) return def exitWaitForOthers(self): self.waitLbl.destroy() del self.waitLbl def setLoserPrize(self, prize): self.loserPrize = prize def setWinnerPrize(self, prize): self.winnerPrize = prize def getLoserPrize(self): return self.loserPrize def getWinnerPrize(self): return self.winnerPrize def winner(self): self.winSfx.play() self.localAv.b_setAnimState('happy') Sequence(Wait(3.5), Func(self.displayGameOver, 'winner')).start() def showPrize(self, amt): self.winSfx.play() self.localAv.b_setAnimState('happy') Sequence(Wait(3.5), Func(self.displayGameOver, 'showPrize', amt)).start() def loser(self): self.loseSfx.play() self.localAv.b_setAnimState('neutral') Sequence(Wait(3.5), Func(self.displayGameOver, 'loser')).start() def displayGameOver(self, scenario, amt = None): if scenario == 'winner': msg = self.winnerMsg % self.winnerPrize self.prizeHigh.play() elif scenario == 'loser': msg = self.loserMsg % self.loserPrize self.prizeLow.play() elif scenario == 'showPrize': msg = random.choice(self.allWinnerMsgs) % amt self.prizeHigh.play() self.gameOverDialog = GlobalDialog(message=msg, style=3, doneEvent='gameOverAck') self.acceptOnce('gameOverAck', self.__handleGameOverAck) self.gameOverDialog.show() def deleteGameOverDialog(self): self.ignore('gameOverAck') if hasattr(self, 'gameOverDialog'): self.gameOverDialog.cleanup() del self.gameOverDialog def __handleGameOverAck(self): self.fsm.requestFinalState() Sequence(Func(base.transitions.irisOut, 1.0), Wait(1.2), Func(self.d_leaving), Func(self.headBackToMinigameArea)).start() def headBackToMinigameArea(self): whereName = ZoneUtil.getWhereName(CIGlobals.MinigameAreaId) loaderName = ZoneUtil.getLoaderName(CIGlobals.MinigameAreaId) requestStatus = {'zoneId': CIGlobals.MinigameAreaId, 'hoodId': CIGlobals.MinigameArea, 'where': whereName, 'how': 'teleportIn', 'avId': base.localAvatar.doId, 'shardId': None, 'loader': loaderName} self.cr.playGame.hood.fsm.request('quietZone', [requestStatus]) return def abort(self): self.headBackToMinigameArea() def load(self): self.fsm.request('start') base.transitions.irisIn() def d_leaving(self): """ Tell the AI that we are leaving. """ self.sendUpdate('leaving', []) def allPlayersReady(self): self.fsm.request('play') def enterPlay(self): self.playMinigameMusic() def exitPlay(self): self.stopMinigameMusic() def enterOff(self): pass def exitOff(self): pass def enterGameOver(self, winner, winnerDoId, allPrize): if winner: if self.localAvId in winnerDoId: self.winner() else: self.loser() else: self.showPrize(allPrize) def exitGameOver(self): self.deleteGameOverDialog() def gameOver(self, winner = 0, winnerDoId = [], allPrize = 0): self.fsm.request('gameOver', [winner, winnerDoId, allPrize]) def setMinigameMusic(self, path): self.musicPath = path def getMinigameMusic(self): return self.musicPath def playMinigameMusic(self): self.stopMinigameMusic() self.music = base.loadMusic(self.musicPath) self.music.setLoop(True) self.music.setVolume(0.7) self.music.play() def stopMinigameMusic(self): if self.music: self.music.stop() self.music = None return def d_ready(self): self.sendUpdate('ready', []) def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) def disable(self): DistributedObject.DistributedObject.disable(self) base.localAvatar.setPosHpr(0, 0, 0, 0, 0, 0) self.fsm.requestFinalState() del self.fsm self.winSfx = None self.loseSfx = None self.prizeHigh = None self.prizeLow = None self.headPanels.delete() self.headPanels = None self.finalScoreUI.unload() self.finalScoreUI = None return
class ToonHood(Hood.Hood): def __init__(self, parentFSM, doneEvent, dnaStore, hoodId): Hood.Hood.__init__(self, parentFSM, doneEvent, dnaStore, hoodId) self.safeZoneLoader = None self.townLoader = None self.fsm = ClassicFSM('Hood', [State('off', self.enterOff, self.exitOff), State('safeZoneLoader', self.enterSafeZoneLoader, self.exitSafeZoneLoader, ['quietZone', 'townLoader']), State('townLoader', self.enterTownLoader, self.exitTownLoader, ['quietZone', 'safeZoneLoader']), State('quietZone', self.enterQuietZone, self.exitQuietZone, ['safeZoneLoader', 'townLoader'])], 'off', 'off') self.fsm.enterInitialState() return def loadLoader(self, requestStatus): loader = requestStatus['loader'] if loader == 'safeZoneLoader': if self.safeZoneLoader: self.loader = self.safeZoneLoader(self, self.fsm.getStateNamed('safeZoneLoader'), self.loaderDoneEvent) self.loader.load() else: self.notify.error('ToonHood.ToonHood.safeZoneLoader cannot be None!' % loader) elif loader == 'townLoader': if self.townLoader: self.loader = self.townLoader(self, self.fsm.getStateNamed('townLoader'), self.loaderDoneEvent) self.loader.load(requestStatus['zoneId']) else: self.notify.error('Unknown loader %s!' % loader) def enterTownLoader(self, requestStatus): self.acceptOnce(self.loaderDoneEvent, self.handleTownLoaderDone) self.loader.enter(requestStatus) self.spawnTitleText(requestStatus['zoneId']) def exitTownLoader(self): taskMgr.remove('titleText') self.hideTitleText() self.ignore(self.loaderDoneEvent) self.loader.exit() self.loader.unload() del self.loader def handleTownLoaderDone(self): doneStatus = self.loader.getDoneStatus() if self.isSameHood(doneStatus): self.fsm.request('quietZone', [doneStatus]) else: self.doneStatus = doneStatus messenger.send(self.doneEvent) def load(self): Hood.Hood.load(self) self.whiteFogColor = Vec4(0.8, 0.8, 0.8, 1) self.underwaterFogColor = Vec4(0.0, 0.0, 0.6, 1.0) def unload(self): del self.safeZoneLoader Hood.Hood.unload(self) def enter(self, requestStatus): self.loadLoader(requestStatus) Hood.Hood.enter(self, requestStatus) def exit(self): Hood.Hood.exit(self) def setUnderwaterFog(self): if base.wantFog: self.fog.setColor(self.underwaterColor) self.fog.setLinearRange(0.1, 100.0) render.setFog(self.fog) self.sky.setFog(self.fog) def setWhiteFog(self): if base.wantFog: self.fog.setColor(self.whiteFogColor) self.fog.setLinearRange(0.0, 400.0) render.clearFog() render.setFog(self.fog) self.sky.clearFog() self.sky.setFog(self.fog) def setNoFog(self): if base.wantFog: render.clearFog() self.sky.clearFog()
class DistributedWeatherCycleAI(DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedWeatherCycleAI') def __init__(self, air): DistributedObjectAI.__init__(self, air) self.fsm = ClassicFSM(self.__class__.__name__, [ State('off', self.enterOff, self.exitOff, ['morning']), State('morning', self.enterMorning, self.exitMorning, ['afternoon']), State('afternoon', self.enterAfternoon, self.exitAfternoon, ['evening']), State('evening', self.enterEvening, self.exitEvening, ['midnight']), State('midnight', self.enterMidnight, self.exitMidnight, ['morning']) ], 'off', 'off') self.fsm.enterInitialState() self.duration = 0 def generate(self): DistributedObjectAI.generate(self) def announceGenerate(self): DistributedObjectAI.announceGenerate(self) taskMgr.doMethodLater(self.getDuration(), self.update, 'update-time') def delete(self): DistributedObjectAI.delete(self) taskMgr.remove('update-time') def update(self, task): self.b_setState(self.fsm.getCurrentState()._State__transitions[0]) return task.again def setState(self, state): self.fsm.request(state) def d_setState(self, state): self.sendUpdate('setState', [state]) def b_setState(self, state): self.setState(state) self.d_setState(state) def getState(self): return self.fsm.getCurrentState()._State__name def setDuration(self, duration): self.duration = duration def d_setDuration(self, duration): self.sendUpdate('setDuration', [duration]) def b_setDuration(self, duration): self.setDuration(duration) self.d_setDuration(duration) def getDuration(self): return self.duration def enterOff(self): pass def exitOff(self): pass def enterMorning(self): pass def exitMorning(self): pass def enterAfternoon(self): pass def exitAfternoon(self): pass def enterEvening(self): pass def exitEvening(self): pass def enterMidnight(self): pass def exitMidnight(self): pass
class Playground(Place.Place): notify = directNotify.newCategory('Playground') def __init__(self, loader, parentFSM, doneEvent): Place.Place.__init__(self, loader, doneEvent) self.fsm = ClassicFSM('Playground', [State('start', self.enterStart, self.exitStart, ['walk', 'teleportIn', 'tunnelOut', 'doorOut']), State('teleportIn', self.enterTeleportIn, self.exitTeleportIn, ['walk', 'acknowledgeDeath']), State('walk', self.enterWalk, self.exitWalk, ['teleportOut', 'stop', 'shtickerBook', 'died', 'tunnelIn']), State('teleportOut', self.enterTeleportOut, self.exitTeleportOut, ['teleportIn', 'stop']), State('stop', self.enterStop, self.exitStop, ['walk', 'died', 'station', 'teleportOut', 'doorIn']), State('shtickerBook', self.enterShtickerBook, self.exitShtickerBook, ['teleportOut', 'walk']), State('tunnelOut', self.enterTunnelOut, self.exitTeleportOut, ['walk']), State('final', self.enterFinal, self.exitFinal, ['start']), State('died', self.enterDied, self.exitDied, ['final']), State('station', self.enterStation, self.exitStation, ['teleportOut', 'walk']), State('doorIn', self.enterDoorIn, self.exitDoorIn, ['stop']), State('doorOut', self.enterDoorOut, self.exitDoorOut, ['walk']), State('tunnelIn', self.enterTunnelIn, self.exitTunnelIn, ['stop']), State('acknowledgeDeath', self.enterAcknowledgeDeath, self.exitAcknowledgeDeath, ['walk'])], 'start', 'final') self.parentFSM = parentFSM def enter(self, requestStatus): Place.Place.enter(self) self.fsm.enterInitialState() messenger.send('enterPlayground') if self.loader.music: if self.__class__.__name__ == 'CTPlayground': volume = 2.0 else: volume = 0.8 base.playMusic(self.loader.music, looping=1, volume=volume) self.loader.geom.reparentTo(render) self.loader.hood.startSky() self.zoneId = requestStatus['zoneId'] if base.cr.playGame.suitManager: base.cr.playGame.suitManager.d_requestSuitInfo() how = requestStatus['how'] self.fsm.request(how, [requestStatus]) def exit(self): self.ignoreAll() messenger.send('exitPlayground') self.loader.geom.reparentTo(hidden) self.loader.hood.stopSky() if self.loader.music: self.loader.music.stop() if self.loader.bossBattleMusic: self.loader.bossBattleMusic.stop() if self.loader.battleMusic: self.loader.battleMusic.stop() if self.loader.invasionMusic: self.loader.invasionMusic.stop() if self.loader.tournamentMusic: self.loader.tournamentMusic.stop() Place.Place.exit(self) def load(self): Place.Place.load(self) self.parentFSM.getStateNamed('playground').addChild(self.fsm) def unload(self): self.parentFSM.getStateNamed('playground').removeChild(self.fsm) del self.parentFSM del self.fsm self.ignoreAll() Place.Place.unload(self) def enterStation(self): base.localAvatar.startPosHprBroadcast() base.localAvatar.d_broadcastPositionNow() def exitStation(self): base.localAvatar.stopPosHprBroadcast() def enterWalk(self, teleportIn = 0): Place.Place.enterWalk(self, teleportIn) if base.localAvatar.zoneId != CIGlobals.RecoverAreaId: base.localAvatar.startMonitoringHP() def exitWalk(self): if base.localAvatar.zoneId != CIGlobals.RecoverAreaId: base.localAvatar.stopMonitoringHP() Place.Place.exitWalk(self) def enterTeleportIn(self, requestStatus): if base.localAvatar.getHealth() < 1: requestStatus['nextState'] = 'acknowledgeDeath' else: requestStatus['nextState'] = 'walk' x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId(self.loader.hood.id) base.localAvatar.detachNode() base.localAvatar.setPosHpr(render, x, y, z, h, p, r) Place.Place.enterTeleportIn(self, requestStatus)
class Toon(Avatar.Avatar, ToonHead, ToonDNA.ToonDNA): notify = directNotify.newCategory("Toon") def __init__(self, cr, mat=0): self.cr = cr try: self.Toon_initialized return except: self.Toon_initialized = 1 Avatar.Avatar.__init__(self, mat) ToonDNA.ToonDNA.__init__(self) ToonHead.__init__(self, cr) self.collsSetup = False self.forwardSpeed = 0.0 self.rotateSpeed = 0.0 self.strafeSpeed = 0.0 self.avatarType = CIGlobals.Toon self.track = None self.standWalkRunReverse = None self.playingAnim = None self.playingRate = None self.tag = None self.money = 0 self.lookAtTrack = None self.portal1 = None self.portal2 = None self.spineA = NodePath() self.tokenIcon = None self.tokenIconIval = None self.fallSfx = base.audio3d.loadSfx( "phase_4/audio/sfx/MG_cannon_hit_dirt.ogg") base.audio3d.attachSoundToObject(self.fallSfx, self) self.eyes = loader.loadTexture("phase_3/maps/eyes.jpg", "phase_3/maps/eyes_a.rgb") self.myTaskId = random.uniform(0, 1231231232132131231232) self.closedEyes = loader.loadTexture("phase_3/maps/eyesClosed.jpg", "phase_3/maps/eyesClosed_a.rgb") self.soundChatBubble = loader.loadSfx( "phase_3/audio/sfx/GUI_balloon_popup.ogg") self.shadowCaster = None self.accessories = [] self.chatSoundDict = {} self.backpack = None self.forceRunSpeed = False self.animFSM = ClassicFSM('Toon', [ State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('swim', self.enterSwim, self.exitSwim), State('walk', self.enterWalk, self.exitWalk), State('run', self.enterRun, self.exitRun), State('bow', self.enterBow, self.exitBow), State('openBook', self.enterOpenBook, self.exitOpenBook), State('readBook', self.enterReadBook, self.exitReadBook), State('closeBook', self.enterCloseBook, self.exitCloseBook), State('teleportOut', self.enterTeleportOut, self.exitTeleportOut), State('teleportIn', self.enterTeleportIn, self.exitTeleportIn), State('died', self.enterDied, self.exitDied), State('fallFWD', self.enterFallFWD, self.exitFallFWD), State('fallBCK', self.enterFallBCK, self.exitFallBCK), State('jump', self.enterJump, self.exitJump), State('leap', self.enterLeap, self.exitLeap), State('laugh', self.enterLaugh, self.exitLaugh), State('happy', self.enterHappyJump, self.exitHappyJump), State('shrug', self.enterShrug, self.exitShrug), State('hdance', self.enterHDance, self.exitHDance), State('wave', self.enterWave, self.exitWave), State('scientistEmcee', self.enterScientistEmcee, self.exitScientistEmcee), State('scientistWork', self.enterScientistWork, self.exitScientistWork), State('scientistGame', self.enterScientistGame, self.exitScientistGame), State('scientistJealous', self.enterScientistJealous, self.exitScientistJealous), State('cringe', self.enterCringe, self.exitCringe), State('conked', self.enterConked, self.exitConked), State('win', self.enterWin, self.exitWin), State('walkBack', self.enterWalkBack, self.exitWalkBack), State('deadNeutral', self.enterDeadNeutral, self.exitDeadNeutral), State('deadWalk', self.enterDeadWalk, self.exitDeadWalk), State('squish', self.enterSquish, self.exitSquish), State('Happy', self.enterHappy, self.exitHappy), State('Sad', self.enterSad, self.exitSad), State('Swim', self.enterSwim, self.exitSwim) ], 'off', 'off') animStateList = self.animFSM.getStates() self.animFSM.enterInitialState() if not hasattr(self, 'uniqueName'): self.uniqueName = types.MethodType(uniqueName, self) self.activities = { ACT_DIE: Die(self), ACT_VICTORY_DANCE: VictoryDance(self), ACT_TOON_BOW: Bow(self), ACT_JUMP: Jump(self) } def setActivity(self, act, timestamp=0): Avatar.Avatar.setActivity(self, act, timestamp) if act == ACT_NONE: self.animFSM.request("Happy") def getUpperBodySubpart(self): if self.getAnimal() == "dog": return ["torso-top", "head"] return ["torso-top"] def getLowerBodySubpart(self): return ["legs", "torso-pants"] def getRightHandNode(self): return self.find("**/def_joint_right_hold") def getLeftHandNode(self): return self.find("**/def_joint_left_hold") def getHeadNode(self): return self.getPart('head') def getEyePoint(self): # middle of the head return Point3(0, 0, self.getHeight() - (self.getHeadHeight() / 2.0)) def setForceRunSpeed(self, flag): self.forceRunSpeed = flag def resetTorsoRotation(self): if not self.isEmpty(): spine = self.find("**/def_spineB") if not spine.isEmpty(): spine.setH(0) spine.detachNode() self.getPart("legs").setH(0) self.releaseJoint("torso", "def_spineB") def showAvId(self): pass def showName(self): pass def getNametagJoints(self): joints = [] for lodName in self.getLODNames(): bundle = self.getPartBundle('legs', lodName) joint = bundle.findChild('joint_nameTag') if joint: joints.append(joint) return joints def enterHappy(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = None self.standWalkRunReverse = (('neutral', 1.0), ('walk', 1.0), ('run', 1.0), ('walk', -1.0), ('strafe', 1.0), ('strafe', -1.0)) self.setSpeed(self.forwardSpeed, self.rotateSpeed) def exitHappy(self): self.standWalkRunReverse = None self.stop() def enterSad(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'sad' self.standWalkRunReverse = (('dneutral', 1.0), ('dwalk', 1.2), ('dwalk', 1.2), ('dwalk', -1.0)) self.setSpeed(0, 0) def exitSad(self): self.standWalkRunReverse = None self.stop() #if hasattr(self, 'doId'): # if hasattr(base, 'localAvatar'): # if base.localAvatar.doId == self.doId: # self.controlManager.enableAvatarJump() def setSpeed(self, forwardSpeed, rotateSpeed, strafeSpeed=0.0): if self.forceRunSpeed: forwardSpeed = CIGlobals.RunCutOff self.forwardSpeed = forwardSpeed self.rotateSpeed = rotateSpeed self.strafeSpeed = strafeSpeed action = None if self.standWalkRunReverse != None: rotateCutOff = CIGlobals.RotateCutOff if not self.isLocalAvatar( ) else CIGlobals.WalkCutOff if strafeSpeed < CIGlobals.StrafeCutOff and strafeSpeed > -CIGlobals.StrafeCutOff: self.resetTorsoRotation() if forwardSpeed >= CIGlobals.RunCutOff: action = CIGlobals.RUN_INDEX elif forwardSpeed > CIGlobals.WalkCutOff: action = CIGlobals.WALK_INDEX elif forwardSpeed < -CIGlobals.WalkCutOff: action = CIGlobals.REVERSE_INDEX elif abs(rotateSpeed) > rotateCutOff: action = CIGlobals.WALK_INDEX elif abs(strafeSpeed) > CIGlobals.RunCutOff: action = CIGlobals.RUN_INDEX elif abs(strafeSpeed) > CIGlobals.WalkCutOff: action = CIGlobals.WALK_INDEX else: action = CIGlobals.STAND_INDEX if abs(strafeSpeed) > CIGlobals.WalkCutOff: spine = self.find("**/def_spineB") if spine.isEmpty(): spine = self.controlJoint(None, "torso", "def_spineB") movementVec = Vec3(strafeSpeed, forwardSpeed, 0) movementVec.normalize() movementAngle = rad2Deg( math.atan2(movementVec[1], movementVec[0])) - 90.0 if action == CIGlobals.REVERSE_INDEX: movementAngle -= 180 spine.setH(-movementAngle) self.getPart('legs').setH(movementAngle) anim, rate = self.standWalkRunReverse[action] if anim != self.playingAnim or rate != self.playingRate or self.forcedTorsoAnim != self.lastForcedTorsoAnim: self.playingAnim = anim self.playingRate = rate self.lastForcedTorsoAnim = self.forcedTorsoAnim if self.forcedTorsoAnim is None: self.loop(anim) else: # Whatever happens to the legs should also happen on the pants. self.loop(anim, partName='torso-pants') self.loop(anim, partName='legs') self.setPlayRate(rate, anim) return action def enterSquish(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'squish' sound = loader.loadSfx('phase_9/audio/sfx/toon_decompress.ogg') lerpTime = 0.1 node = self.getGeomNode().getChild(0) origScale = node.getScale() if hasattr(self, 'uniqueName'): name = self.uniqueName('getSquished') else: name = 'getSquished' self.track = Sequence(LerpScaleInterval(node, lerpTime, VBase3(2, 2, 0.025), blendType='easeInOut'), Wait(1.0), Parallel( Sequence( Wait(0.4), LerpScaleInterval(node, lerpTime, VBase3(1.4, 1.4, 1.4), blendType='easeInOut'), LerpScaleInterval(node, lerpTime / 2.0, VBase3(0.8, 0.8, 0.8), blendType='easeInOut'), LerpScaleInterval( node, lerpTime / 3.0, origScale, blendType='easeInOut')), ActorInterval(self, 'happy', startTime=0.2), SoundInterval(sound)), name=name) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.squishDone, [callback, extraArgs]) self.track.delayDelete = DelayDelete.DelayDelete(self, name) self.track.start(ts) def squishDone(self, callback=None, extraArgs=[]): self.__doCallback(callback, extraArgs) def exitSquish(self): if self.track: self.ignore(self.track.getName()) DelayDelete.cleanupDelayDeletes(self.track) self.track.finish() self.track = None self.playingAnim = 'neutral' def enterDeadNeutral(self, ts=0, callback=None, extraArgs=[]): self.loop('dneutral') def exitDeadNeutral(self): self.stop() def enterDeadWalk(self, ts=0, callback=None, extraArgs=[]): self.loop('dwalk') def exitDeadWalk(self): self.stop() def setBackpack(self, pack): self.backpack = pack def getGhost(self): return 0 def updateChatSoundDict(self): self.chatSoundDict['exclaim'] = base.audio3d.loadSfx( self.getToonAnimalNoise('exclaim')) self.chatSoundDict['question'] = base.audio3d.loadSfx( self.getToonAnimalNoise('question')) self.chatSoundDict['short'] = base.audio3d.loadSfx( self.getToonAnimalNoise('short')) self.chatSoundDict['medium'] = base.audio3d.loadSfx( self.getToonAnimalNoise('med')) self.chatSoundDict['long'] = base.audio3d.loadSfx( self.getToonAnimalNoise('long')) self.chatSoundDict['howl'] = base.audio3d.loadSfx( self.getToonAnimalNoise('howl')) base.audio3d.attachSoundToObject(self.chatSoundDict['exclaim'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['question'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['short'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['medium'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['long'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['howl'], self.getPart('head')) def __actAsGone(self): if self.nametag3d: self.nametag3d.hide() if self.getShadow(): self.getShadow().hide() if self.tokenIcon: self.tokenIcon.hide() #self.stashBodyCollisions() def __restoreHide(self): if self.tokenIcon: self.tokenIcon.show() if self.getShadow(): self.getShadow().show() if self.nametag3d: self.nametag3d.show() if self.getGeomNode(): self.getGeomNode().setTransparency(False) self.getGeomNode().setAlphaScale(1.0) self.getGeomNode().show() #self.unstashBodyCollisions() def handleGhost(self, flag): alpha = 1.0 if not flag else 0.25 local = self == base.localAvatar if flag: if self.getAccessLevel() >= base.localAvatar.getAccessLevel(): # Other staff members at this access level or higher should # be able to see this avatar still. alpha = 0.25 #self.stashBodyCollisions() elif not local: self.getGeomNode().setTransparency(True) self.getGeomNode().setColorScale(1.0, 1.0, 1.0, 0.0) self.__actAsGone() else: self.__restoreHide() if local: self.getGeomNode().setTransparency(flag) self.getGeomNode().setColorScale(1.0, 1.0, 1.0, alpha) def stopAnimations(self): if hasattr(self, 'animFSM'): if not self.animFSM.isInternalStateInFlux(): self.animFSM.request('off') else: self.notify.warning( "animFSM in flux, state=%s, not requesting off" % self.animFSM.getCurrentState().getName()) else: self.notify.warning("animFSM has been deleted") if self.track != None: self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None return def disable(self): try: self.Toon_disabled except: self.Toon_disabled = 1 self.ignoreAll() self.backpack = None self.collsSetup = False self.stopAnimations() self.removeAdminToken() ToonHead.delete(self) self.deleteCurrentToon() self.chatSoundDict = {} Avatar.Avatar.disable(self) def delete(self): try: self.Toon_deleted except: self.Toon_deleted = 1 del self.animFSM self.forwardSpeed = None self.chatSoundDict = None self.rotateSpeed = None self.avatarType = None self.track = None self.standWalkRunReverse = None self.currentAnim = None self.toon_head = None self.forcedTorsoAnim = None self.lastForcedTorsoAnim = None self.toon_torso = None self.toon_legs = None self.gender = None self.headtype = None self.head = None self.legtype = None self.torsotype = None self.hr = None self.hg = None self.hb = None self.tr = None self.tg = None self.tb = None self.lr = None self.lg = None self.lb = None self.shir = None self.shig = None self.shib = None self.shor = None self.shog = None self.shob = None self.shirt = None self.sleeve = None self.short = None self.tag = None self.money = None self.lookAtTrack = None self.portal1 = None self.portal2 = None self.backpack = None self.fallSfx = None self.eyes = None self.myTaskId = None self.closedEyes = None self.soundChatBubble = None self.lastAction = None self.lastState = None self.playingAnim = None self.playingRate = None self.accessories = None Avatar.Avatar.delete(self) return def initCollisions(self): self.collNodePath.setCollideMask(BitMask32(0)) self.collNodePath.node().setFromCollideMask(CIGlobals.WallBitmask) pusher = CollisionHandlerPusher() pusher.setInPattern("%in") pusher.addCollider(self.collNodePath, self) base.cTrav.addCollider(self.collNodePath, pusher) def deleteCurrentToon(self): if self.shadowCaster: self.shadowCaster.clear() self.shadowCaster = None for accessory in self.accessories: accessory.removeNode() self.accessories = [] self.pupils = [] if 'head' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['head'] if 'torso' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['torso'] if 'legs' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['legs'] self.deleteShadow() self.removePart('head') self.removePart('torso') self.removePart('legs') self.clearPythonData() self.flush() def setAdminToken(self, tokenInstance): if tokenInstance: matPath = tokenInstance.getMaterialPath() self.tokenIcon = loader.loadModel( "phase_3/models/props/staffIcon.bam") self.tokenIcon.reparentTo(self) self.tokenIcon.setScale(0.75) self.tokenIcon.setShaderAuto() # Let's update the material. self.tokenIcon.setBSPMaterial(matPath, 1) # Let's position the icon above the nametag. x, y, z = self.nametag3d.getPos() self.tokenIcon.setPos(Vec3(x, y, z + self.tokenIcon.getSz())) r, g, b, _ = tokenInstance.getColor() # Let's add the glow. glow = loader.loadModel( 'phase_4/models/minigames/particleGlow.bam') glow.reparentTo(self.tokenIcon) glow.setScale(2.50) glow.setColorScale((r, g, b, 0.50), 1) glow.setBSPMaterial('phase_4/maps/particleGlow.mat', 1) glow.setDepthWrite(False, 1) glow.setShaderAuto() glow.setTwoSided(1) self.tokenIconIval = Sequence( LerpHprInterval(self.tokenIcon, duration=3.0, hpr=Vec3(360, 0, 0), startHpr=Vec3(0, 0, 0))) self.tokenIconIval.loop() else: self.removeAdminToken() def removeAdminToken(self): if self.tokenIcon != None and self.tokenIconIval != None: self.tokenIconIval.finish() self.tokenIcon.removeNode() self.tokenIconIval = None self.tokenIcon = None def playChatSfx(self, chatString): if not self.getGhost() or self.doId == base.localAvatar.doId: if "ooo" in chatString.lower(): sfx = self.chatSoundDict['howl'] elif "!" in chatString.lower(): sfx = self.chatSoundDict['exclaim'] elif "?" in chatString.lower(): sfx = self.chatSoundDict['question'] elif len(chatString) <= 9: sfx = self.chatSoundDict['short'] elif 10 <= len(chatString) <= 19: sfx = self.chatSoundDict['medium'] elif len(chatString) >= 20: sfx = self.chatSoundDict['long'] base.playSfx(sfx, node=self) def chatStompComplete(self, chatString): if not self.thoughtInProg and CIGlobals.getSettingsMgr().getSetting( "chs").getValue(): self.playChatSfx(chatString) def setName(self, nameString): Avatar.Avatar.setName(self, nameString) def setDNAStrand(self, dnaStrand, makeTag=1): ToonDNA.ToonDNA.setDNAStrand(self, dnaStrand) self.deleteCurrentToon() self.generateToon(makeTag) def generateMask(self): # No accessories yet. if self.shirt == self.maleTopDNA2maleTop['135'][ 0] or self.shirt == self.maleTopDNA2maleTop['136'][0]: # This toon is wearing the tsa suit, give them some sweet shades. name = 'tsaGlasses' glasses = loader.loadModel( AccessoryGlobals.AccessoryName2Model[name]) glassesNode = self.getPart('head').attachNewNode('glassesNode') glasses.reparentTo(glassesNode) data = AccessoryGlobals.MaskTransExtended[name].get(self.animal) if not data: data = AccessoryGlobals.MaskTrans.get(self.animal) posHprScale = AccessoryGlobals.MaskTrans[self.animal][ self.headLength] else: posHprScale = AccessoryGlobals.MaskTransExtended[name][ self.animal].get(self.headLength) if not posHprScale: posHprScale = AccessoryGlobals.MaskTrans[self.animal][ self.headLength] glasses.setPos(posHprScale[0]) glasses.setHpr(posHprScale[1]) glasses.setScale(posHprScale[2]) self.accessories.append(glassesNode) def generateToon(self, makeTag=1): self.generateLegs() self.generateTorso() self.generateHead() self.setToonColor() self.setClothes() self.setGloves() self.parentToonParts() self.rescaleToon() self.generateMask() # Make torso subparts so we can play a run animation on the pants but another animation on the spine and arms. if self.gender == 'boy': self.makeSubpart("torso-pants", [ "def_left_pant_bottom", "def_left_pant_top", "def_right_pant_bottom", "def_right_pant_top" ], parent="torso") elif self.gender == 'girl': if self.torso == 'dgs_skirt': self.makeSubpart("torso-pants", [ "def_left_skirt_backA", "def_left_skirt_frontA", "def_left_skirt_topA", "def_right_skirt_backA", "def_right_skirt_frontA", "def_right_skirt_topA" ], parent="torso") elif self.torso == 'dgl_skirt': self.makeSubpart("torso-pants", [ "def_left_skirt_bottomA", "def_left_skirt_topA", "def_right_hip" ], parent="torso") else: self.makeSubpart("torso-pants", [ "def_left_skirt_bottomA", "def_left_skirt_topA", "def_right_skirt_bottomA", "def_right_skirt_topA" ], parent="torso") self.makeSubpart("torso-top", ["def_spineB"], parent="torso") Avatar.Avatar.initShadow(self) self.updateChatSoundDict() self.setBlend(frameBlend=True) bodyMat = CIGlobals.getCharacterMaterial(shininess=5, specular=(0.5, 0.5, 0.5, 1)) self.setMaterial(bodyMat, 1) if not hasattr(base, 'localAvatar') or base.localAvatar != self: self.setupPhysics(1.0, self.getHeight()) # We can safely optimize the scene graph and combine nodes since we're done manipulating # the separate pieces. After this point, the separate pieces of the toon are no # longer manipulatable, such as arms, sleeves, shirt, etc. If this needs to be done, # the toon will have to be regenerated. # Don't do it in Make-A-Toon though, as we have to be constantly modifying the pieces. if not self.mat: self.optimize() if makeTag: self.setupNameTag() if self.cr.isShowingPlayerIds: self.showAvId() self.loop('neutral') def optimize(self): self.getPart('legs').flattenStrong() self.postFlatten() def attachTNT(self): self.pies.attachTNT() self.holdTNTAnim() def detachTNT(self): self.pies.detachTNT() self.animFSM.request(self.animFSM.getCurrentState().getName()) def holdTNTAnim(self): self.pose("toss", 22, partName="torso") def parentToonParts(self): self.attach('head', 'torso', 'def_head') self.attach('torso', 'legs', 'joint_hips') def unparentToonParts(self): self.getPart('head').reparentTo(self.getGeomNode()) self.getPart('torso').reparentTo(self.getGeomNode()) self.getPart('legs').reparentTo(self.getGeomNode()) def getHeadHeight(self): animal = self.getAnimal() headScale = ToonGlobals.HeadScales[animal][2] headHeight = ToonGlobals.HeadHeightDict[self.head] * headScale return headHeight def rescaleToon(self): if not self.getHead(): return animal = self.getAnimal() bodyScale = ToonGlobals.BodyScales[animal] headScale = ToonGlobals.HeadScales[animal][2] shoulderHeight = ToonGlobals.LegHeightDict[ self.getLegs()] * bodyScale + ToonGlobals.TorsoHeightDict[ self.getTorso()] * bodyScale height = shoulderHeight + ToonGlobals.HeadHeightDict[ self.getHead()] * headScale bodyScale = ToonGlobals.BodyScales[animal] self.setAvatarScale(bodyScale) self.getPart('head').setScale(headScale) self.setHeight(height) def setGloves(self): color = self.getGloveColor() gloves = self.find('**/hands') gloves.setColor(color) def setClothes(self): shirt, shirtcolor = self.getShirtStyle() short, shortcolor = self.getShortStyle() sleeve, sleevecolor = self.getSleeveStyle() torsot = self.findAllMatches('**/torso-top') torsob = self.findAllMatches('**/torso-bot') sleeves = self.findAllMatches('**/sleeves') torsot.setBSPMaterial(shirt, 1) torsob.setBSPMaterial(short, 1) sleeves.setBSPMaterial(sleeve, 1) torsot.setColor(shirtcolor) sleeves.setColor(sleevecolor) torsob.setColor(shortcolor) def generateLegs(self): ToonGlobals.generateBodyPart(self, 'legs', self.getLegs(), 3, 'shorts') self.find('**/boots_long').stash() self.find('**/boots_short').stash() self.find('**/shoes').stash() def generateTorso(self): ToonGlobals.generateBodyPart(self, 'torso', self.getTorso(), 3, '') def generateHead(self, pat=0): gender = self.getGender() head = self.getAnimal() headtype = self.getHead() ToonHead.generateHead(self, gender, head, headtype) def setToonColor(self): self.setHeadColor() self.setTorsoColor() self.setLegColor() def setLegColor(self): legcolor = self.getLegColor() self.findAllMatches('**/legs').setColor(legcolor) self.findAllMatches('**/feet').setColor(legcolor) def setTorsoColor(self): torsocolor = self.getTorsoColor() self.findAllMatches('**/arms').setColor(torsocolor) self.findAllMatches('**/neck').setColor(torsocolor) self.findAllMatches('**/hands').setColor(1, 1, 1, 1) def enterOff(self, ts=0, callback=None, extraArgs=[]): self.currentAnim = None return def exitOff(self): pass def enterWin(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'win' self.sfx = base.audio3d.loadSfx("phase_3.5/audio/sfx/ENC_Win.ogg") self.sfx.setLoop(True) base.audio3d.attachSoundToObject(self.sfx, self) base.playSfx(self.sfx, node=self, looping=1) self.loop("win") def exitWin(self): self.stop() self.sfx.stop() del self.sfx self.playingAnim = 'neutral' def enterShrug(self, ts=0, callback=None, extraArgs=[]): self.play("shrug") def exitShrug(self): self.exitGeneral() def enterHDance(self, ts=0, callback=None, extraArgs=[]): self.play("hdance") def exitHDance(self): self.exitGeneral() def enterScientistWork(self, ts=0, callback=None, extraArgs=[]): self.loop("scwork") def exitScientistWork(self): self.exitGeneral() def enterScientistEmcee(self, ts=0, callback=None, extraArgs=[]): self.loop("scemcee") def exitScientistEmcee(self): self.exitGeneral() def enterScientistGame(self, ts=0, callback=None, extraArgs=[]): self.loop("scgame") def exitScientistGame(self): self.exitGeneral() def enterScientistJealous(self, ts=0, callback=None, extraArgs=[]): self.loop("scjealous") def exitScientistJealous(self): self.exitGeneral() def enterWave(self, ts=0, callback=None, extraArgs=[]): self.play("wave") def exitWave(self): self.exitGeneral() def enterLaugh(self, ts=0, callback=None, extraArgs=[]): self.setPlayRate(5.0, "neutral") self.loop("neutral") def exitLaugh(self): self.setPlayRate(1.0, "neutral") self.stop() def enterNeutral(self, ts=0, callback=None, extraArgs=[]): if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop("neutral", partName="legs") return self.loop("neutral") self.playingAnim = 'neutral' def exitNeutral(self): self.exitGeneral() self.playingAnim = 'neutral' def exitGeneral(self): self.stop() def enterRun(self, ts=0, callback=None, extraArgs=[]): if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop('run', partName='legs') return self.loop("run") def exitRun(self): self.exitGeneral() def enterWalk(self, ts=0, callback=None, extraArgs=[]): if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop('walk', partName='legs') return self.loop('walk') def exitWalk(self): self.exitGeneral() def enterWalkBack(self, ts=0, callback=None, extraArgs=[]): self.setPlayRate(-1.0, "walk") self.enterWalk() def exitWalkBack(self): self.exitWalk() self.setPlayRate(1.0, "walk") def enterOpenBook(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'book' self.book1 = Actor("phase_3.5/models/props/book-mod.bam", {"chan": "phase_3.5/models/props/book-chan.bam"}) self.book1.reparentTo( self.getPart('torso').find('**/def_joint_right_hold')) self.track = ActorInterval(self, "book", startFrame=CIGlobals.OpenBookFromFrame, endFrame=CIGlobals.OpenBookToFrame, name=self.uniqueName('enterOpenBook')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.__doCallback, [callback, extraArgs]) self.track.start(ts) self.book1.play("chan", fromFrame=CIGlobals.OpenBookFromFrame, toFrame=CIGlobals.OpenBookToFrame) def exitOpenBook(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None if self.book1: self.book1.cleanup() self.book1 = None self.playingAnim = 'neutral' def enterReadBook(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'book' self.book2 = Actor("phase_3.5/models/props/book-mod.bam", {"chan": "phase_3.5/models/props/book-chan.bam"}) self.book2.reparentTo( self.getPart('torso').find('**/def_joint_right_hold')) self.pingpong("book", fromFrame=CIGlobals.ReadBookFromFrame, toFrame=CIGlobals.ReadBookToFrame) self.book2.pingpong("chan", fromFrame=CIGlobals.ReadBookFromFrame, toFrame=CIGlobals.ReadBookToFrame) def exitReadBook(self): if self.book2: self.book2.cleanup() self.book2 = None self.playingAnim = 'neutral' def enterCloseBook(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'book' self.book3 = Actor("phase_3.5/models/props/book-mod.bam", {"chan": "phase_3.5/models/props/book-chan.bam"}) self.book3.reparentTo( self.getPart('torso').find('**/def_joint_right_hold')) self.track = ActorInterval(self, "book", startFrame=CIGlobals.CloseBookFromFrame, endFrame=CIGlobals.CloseBookToFrame, name=self.uniqueName('enterCloseBook')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.__doCallback, [callback, extraArgs]) self.track.start(ts) self.book3.play("chan", fromFrame=CIGlobals.CloseBookFromFrame, toFrame=CIGlobals.CloseBookToFrame) self.lerpLookAt(self.getPart('head'), (0, 0, 0)) def exitCloseBook(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None if self.book3: self.book3.cleanup() self.book3 = None self.playingAnim = 'neutral' def enterTeleportOut(self, ts=0, callback=None, extraArgs=[]): self.notify.info( str(self.doId) + "-" + str(self.zoneId) + ": enterTeleportOut") self.playingAnim = 'tele' self.portal1 = Actor( "phase_3.5/models/props/portal-mod.bam", {"chan": "phase_3.5/models/props/portal-chan.bam"}) self.portal1.play("chan") self.portal1.reparentTo( self.getPart('legs').find('**/def_joint_right_hold')) self.play("tele") if hasattr(self, 'uniqueName'): name = self.uniqueName('enterTeleportOut') else: name = 'enterTeleportOut' self.track = Sequence(Wait(0.4), Func(self.teleportOutSfx), Wait(1.3), Func(self.throwPortal), Wait(1.1), Func(self.__actAsGone), Wait(1.5), name=name) self.track.delayDelete = DelayDelete.DelayDelete(self, name) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), self.teleportOutDone, [callback, extraArgs]) self.track.start(ts) def doPortalBins(self, portal): portal.setBin('portal', 19) portal.setDepthWrite(0) portal.setDepthTest(0) def teleportOutDone(self, callback, requestStatus): self.notify.info( str(self.doId) + "-" + str(self.zoneId) + ": teleportOutDone") self.__doCallback(callback, requestStatus) self.exitTeleportOut() def teleportOutSfx(self): self.outSfx = base.audio3d.loadSfx( "phase_3.5/audio/sfx/AV_teleport.ogg") base.audio3d.attachSoundToObject(self.outSfx, self.portal1) base.playSfx(self.outSfx, node=self) def throwPortal(self): self.doPortalBins(self.portal1) self.portal1.reparentTo(self.getPart('legs').find('**/joint_nameTag')) self.portal1.setScale(CIGlobals.PortalScale) self.portal1.setY(6.5) self.portal1.setH(180) def exitTeleportOut(self): self.notify.info( str(self.doId) + "-" + str(self.zoneId) + ": exitTeleportOut") if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if self.portal1: self.portal1.cleanup() self.portal1 = None if hasattr(self, 'shadow') and self.shadow is not None: self.shadow.show() self.__restoreHide() self.playingAnim = 'neutral' def getTeleportInTrack(self, portal): self.doPortalBins(portal) holeTrack = Sequence() holeTrack.append(Func(portal.reparentTo, self)) pos = Point3(0, -2.4, 0) holeTrack.append(Func(portal.setPos, pos)) holeTrack.append( ActorInterval(portal, 'chan', startTime=3.4, endTime=3.1)) holeTrack.append(Wait(0.6)) holeTrack.append( ActorInterval(portal, 'chan', startTime=3.1, endTime=3.4)) def restorePortal(portal): portal.setPos(0, 0, 0) portal.detachNode() portal.clearBin() portal.clearDepthTest() portal.clearDepthWrite() holeTrack.append(Func(restorePortal, portal)) toonTrack = Sequence(Wait(0.3), Func(self.__restoreHide), ActorInterval(self, 'happy', startTime=0.45)) if hasattr(self, 'uniqueName'): trackName = self.uniqueName('teleportIn') else: trackName = 'teleportIn' return Parallel(toonTrack, holeTrack, name=trackName) def enterTeleportIn(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'happy' self.portal2 = Actor( "phase_3.5/models/props/portal-mod.bam", {"chan": "phase_3.5/models/props/portal-chan.bam"}) self.show() self.getGeomNode().hide() self.nametag3d.hide() self.track = self.getTeleportInTrack(self.portal2) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), self.teleportInDone, [callback, extraArgs]) if hasattr(self, 'acquireDelayDelete'): self.track.delayDelete = DelayDelete.DelayDelete( self, self.track.getName()) self.track.start(ts) def teleportInDone(self, callback, extraArgs): self.exitTeleportIn() self.__doCallback(callback, extraArgs) def exitTeleportIn(self): if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if self.portal2: self.portal2.cleanup() self.portal2 = None if self.nametag3d: self.nametag3d.show() self.playingAnim = 'neutral' def enterFallFWD(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'fallf' self.play("fallf") Sequence(Wait(0.5), SoundInterval(self.fallSfx, node=self)).start() def exitFallFWD(self): self.exitGeneral() self.playingAnim = 'neutral' def enterFallBCK(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'fallb' self.play("fallb") Sequence(Wait(0.5), SoundInterval(self.fallSfx, node=self)).start() def exitFallBCK(self): self.playingAnim = 'neutral' self.exitGeneral() def enterHappyJump(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'happy' self.play("happy") def exitHappyJump(self): self.exitGeneral() self.playingAnim = 'neutral' def enterSwim(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'swim' self.loop("swim") self.resetTorsoRotation() toon = self.getGeomNode() toon.setP(-89.0) if self.shadow: self.shadow.hide() self.swimBobTrack = Sequence( LerpPosInterval(toon, duration=1, pos=(0, -3, 3), startPos=(0, -3, 4), blendType='easeInOut'), LerpPosInterval(toon, duration=1, pos=(0, -3, 4), startPos=(0, -3, 3), blendType='easeInOut')) self.swimBobTrack.loop() self.nametag3d.setZ(5.0) def exitSwim(self): self.swimBobTrack.finish() del self.swimBobTrack if self.shadow: self.shadow.show() self.exitGeneral() self.getGeomNode().setPosHpr(0, 0, 0, 0, 0, 0) nt = self.nametag3d nt.setX(0) nt.setY(0) nt.setZ(self.getHeight() + 0.5) self.playingAnim = 'neutral' def enterDied(self, ts=0, callback=None, extraArgs=[]): def shouldDisableGags(): if hasattr(self, 'disableGags'): self.disableGags() if hasattr(self, 'setEquippedAttack'): self.setEquippedAttack(-1) self.playingAnim = 'lose' self.isdying = True self.play("lose") self.track = Sequence(Func(self.clearForcedTorsoAnim), Func(shouldDisableGags), Wait(2.2), Func(self.dieSfx), Wait(2.8), self.getGeomNode().scaleInterval( 2, Point3(0.01), startScale=(self.getGeomNode().getScale())), Func(self.delToon), name=self.uniqueName('enterDied')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.diedDone, [callback, extraArgs]) self.track.delayDelete = DelayDelete.DelayDelete( self, 'enterTeleportOut') self.track.start(ts) def diedDone(self, callback, extraArgs): self.__doCallback(callback, extraArgs) self.exitDied() def __doCallback(self, callback, extraArgs): if callback: if extraArgs: callback(*extraArgs) else: callback() def dieSfx(self): self.Losesfx = base.audio3d.loadSfx("phase_5/audio/sfx/ENC_Lose.ogg") base.audio3d.attachSoundToObject(self.Losesfx, self) base.playSfx(self.Losesfx, node=self) def delToon(self): self.isdead = True def exitDied(self): if self.track != None: self.ignore(self.track.getDoneEvent()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if hasattr(self, 'enableGags'): self.enableGags() self.rescaleToon() self.playingAnim = 'neutral' def enterBow(self, ts=0, callback=None, extraArgs=[]): self.play("bow") self.playingAnim = 'bow' def exitBow(self): self.exitGeneral() self.playingAnim = 'neutral' def enterJump(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'jump' self.loop("jump") def exitJump(self): self.exitGeneral() self.playingAnim = 'neutral' def enterLeap(self, ts=0, callback=None, extraArgs=[]): self.playingAnim = 'leap' self.loop("leap") def exitLeap(self): self.exitGeneral() self.playingAnim = 'neutral' def enterCringe(self, ts=0, callback=None, extraArgs=[]): self.play("cringe") def exitCringe(self): self.exitGeneral() def enterConked(self, ts=0, callback=None, extraArgs=[]): self.play("conked") def exitConked(self): self.exitGeneral()
class DistributedCityCart(DistributedNode): notify = directNotify.newCategory('DistributedCityCart') def __init__(self, cr): DistributedNode.__init__(self, cr) self.fsm = ClassicFSM('DistributedCityCart', [State('off', self.enterOff, self.exitOff), State('pathFollow', self.enterPathFollow, self.exitPathFollow), State('collision', self.enterCollision, self.exitCollision)], 'off', 'off') self.fsm.enterInitialState() self.suitInCar = None self.cart = None self.honkSfxPath = 'phase_14/audio/sfx/cogtropolis_citycar_driveby_horn.mp3' self.cartModelPath = 'phase_12/models/bossbotHQ/Coggolf_cart3.bam' self.moPaths = ['phase_14/models/paths/ct-citycar-drivepath-1.egg', 'phase_14/models/paths/ct-citycar-drivepath-2.egg', 'phase_14/models/paths/ct-citycar-drivepath-3.egg', 'phase_14/models/paths/ct-citycar-drivepath-4.egg', 'phase_14/models/paths/ct-citycar-drivepath-5.egg', 'phase_14/models/paths/ct-citycar-drivepath-6.egg'] self.moPath = None self.soundEngineLoop = None self.soundDriveByHorn = None self.ivalTDisplace = None self.pathIndex = None self.wheelSpinTrack = None self.collNodePath = None self.soundDriveBy = None return def setIvalTDisplace(self, displace): self.ivalTDisplace = displace def setPathIndex(self, index): self.pathIndex = index def setState(self, state, timestamp): ts = ClockDelta.globalClockDelta.localElapsedTime(timestamp) self.fsm.request(state, [ts]) def enterOff(self): pass def exitOff(self): pass def enterPathFollow(self, ts): duration = CityCartGlobals.index2Duration[self.pathIndex] self.moPath = NURBSMopath.NURBSMopath(self.moPaths[self.pathIndex], name=self.uniqueName('DCityCart_moPath')) startT = 0.0 if ts > 0.0: startT = ts % duration * (1.0 / duration) self.moPath.play(self, loop=True, duration=duration, startT=startT) base.taskMgr.add(self.__drive, self.uniqueName('DCityCart.drive')) self.wheelSpinTrack = Parallel() for name in ['leftFrontWheel', 'rightBackWheel', 'rightFrontWheel', 'leftBackWheel']: wheel = self.find('**/' + name) self.wheelSpinTrack.append(LerpHprInterval(wheel, duration=0.1, hpr=(0, 360, 0), startHpr=(0, 0, 0))) self.wheelSpinTrack.loop() self.accept('enter' + self.collNodePath.node().getName(), self.__handleRanOver) def __handleRanOver(self, entry): self.suitInCar.setChat(CityCartGlobals.SuitRanOverTaunt) self.sendUpdate('hitByCar') self.cr.playGame.getPlace().fsm.request('stop') base.localAvatar.b_setAnimState('squish', callback=self.cr.playGame.getPlace().fsm.request, extraArgs=['walk']) def __drive(self, task): if base.localAvatar.getDistance(self) < 10.0: if self.soundDriveByHorn.status() == self.soundDriveByHorn.READY: wantsToHonk = random.randint(0, 3) if wantsToHonk == 3: base.playSfx(self.soundDriveByHorn) return task.cont elif base.localAvatar.getDistance(self) < 20.0: if self.soundDriveBy.status() == self.soundDriveBy.READY: base.playSfx(self.soundDriveBy) return task.cont return task.cont def exitPathFollow(self): self.ignore('enter' + self.collNodePath.node().getName()) if self.wheelSpinTrack: self.wheelSpinTrack.finish() self.wheelSpinTrack = None if self.moPath: self.moPath.stop() self.moPath = None return def enterCollision(self, ts): pass def exitCollision(self): pass def generate(self): DistributedNode.generate(self) self.cart = loader.loadModel(self.cartModelPath) self.cart.reparentTo(self) self.cart.setH(180) heads = [] for head in CIGlobals.SuitBodyData.keys(): if CIGlobals.SuitBodyData[head][0] != 'B': heads.append(head) head = random.choice(heads) suitType = CIGlobals.SuitBodyData[head][0] suitDept = CIGlobals.SuitBodyData[head][1] self.suitInCar = Suit() self.suitInCar.generateSuit(suitType, head, suitDept, 137, 0, False) self.suitInCar.loop('sit') self.suitInCar.disableRay() self.suitInCar.setScale(0.7) self.suitInCar.setH(180) self.suitInCar.setPos(0, -1, -1.5) self.suitInCar.reparentTo(self.cart.find('**/seat1')) self.soundEngineLoop = base.audio3d.loadSfx('phase_6/audio/sfx/KART_Engine_loop_0.wav') base.audio3d.attachSoundToObject(self.soundEngineLoop, self) base.playSfx(self.soundEngineLoop, looping=1) self.soundDriveByHorn = base.audio3d.loadSfx(self.honkSfxPath) base.audio3d.attachSoundToObject(self.soundDriveByHorn, self) self.soundDriveBy = base.audio3d.loadSfx('phase_14/audio/sfx/cogtropolis_citycar_driveby.mp3') base.audio3d.attachSoundToObject(self.soundDriveBy, self) sphere = CollisionSphere(0, 0, 0, 2.5) sphere.setTangible(0) node = CollisionNode(self.uniqueName('cartSphere')) node.setCollideMask(CIGlobals.WallBitmask) node.addSolid(sphere) self.collNodePath = self.attachNewNode(node) self.collNodePath.setZ(1.5) self.collNodePath.setSy(2.0) self.collNodePath.setSx(1.75) def disable(self): self.fsm.requestFinalState() if self.moPath: self.moPath.stop() self.moPath = None self.moPaths = None self.honkSfxPath = None self.cartModelPath = None self.soundEngineLoop = None self.soundDriveBy = None if self.suitInCar: self.suitInCar.disable() self.suitInCar.delete() self.suitInCar = None if self.cart: self.cart.removeNode() self.cart = None del self.fsm DistributedNode.disable(self) return
class UberDog(AIRepository): notify = directNotify.newCategory("UberDog") def __init__( self, mdip, mdport, esip, esport, dcFileNames, serverId, minChannel, maxChannel): AIRepository.__init__( self, mdip, mdport, esip, esport, dcFileNames, serverId, minChannel, maxChannel, dcSuffix = 'UD') # We're responsible for keeping track of who's online with which avatar self.onlineAccountDetails = {} self.onlineAvatars = {} self.onlinePlayers = {} self.pending={} self.doId2doCache={} if hasattr(self, 'setVerbose'): if ConfigVariableBool('verbose-uberrepository', 0).getValue(): self.setVerbose(1) # The AI State machine self.fsm = ClassicFSM( 'UberDog', [ State('off', self.enterOff, self.exitOff, ['connect']), State('connect', self.enterConnect, self.exitConnect, ['noConnection', 'playGame',]), State('playGame', self.enterPlayGame, self.exitPlayGame, ['noConnection']), State('noConnection', self.enterNoConnection, self.exitNoConnection, ['connect'])], # initial state 'off', # final state 'off', ) self.fsm.enterInitialState() self.fsm.request("connect") def _connected(self): """ Callback for when we successfully connect to the otp_server cluster. """ self.setConnectionName("UberDog") AIRepository._connected(self) # Listen for Account and Avatar online/offline messages self.registerForChannel(CHANNEL_PUPPET_ACTION) self.fsm.request("playGame") def dispatchUpdateToDoId(self, dclassName, fieldName, doId, args, channelId=None): # dispatch immediately to local object if it's local, otherwise send # it over the wire obj = self.doId2do.get(doId) if obj is not None: assert obj.__class__.__name__ == (dclassName + self.dcSuffix) method = getattr(obj, fieldName) method(*args) else: self.sendUpdateToDoId(dclassName, fieldName, doId, args, channelId) def dispatchUpdateToGlobalDoId(self, dclassName, fieldName, doId, args): # dispatch immediately to local object if it's local, otherwise send # it over the wire obj = self.doId2do.get(doId) if obj is not None: assert obj.__class__.__name__ == dclassName method = getattr(obj, fieldName) method(*args) else: self.sendUpdateToGlobalDoId(dclassName, fieldName, doId, args) @report(types = ['args'], dConfigParam = 'avatarmgr') def handleAccountUsage(self, di): priorAccount = di.getUint32() # Historic - used only in __dev__ atm newAccount = di.getUint32() if priorAccount == 0 and newAccount == 0: assert self.notify.debug("priorAccount==0 and newAccount==0, ignoring accountUsage message") return accountDetailRecord = AccountDetailRecord() accountDetailRecord.openChatEnabled = (di.getString() == "YES") accountDetailRecord.createFriendsWithChat = (di.getString() == "YES") accountDetailRecord.chatCodeCreation = (di.getString() == "YES") access = di.getString() if access == "VELVET": access = OTPGlobals.AccessVelvetRope elif access == "FULL": access = OTPGlobals.AccessFull else: access = OTPGlobals.AccessUnknown accountDetailRecord.piratesAccess = access accountDetailRecord.familyAccountId = di.getInt32() accountDetailRecord.playerAccountId = di.getInt32() accountDetailRecord.playerName = di.getString() accountDetailRecord.playerNameApproved = di.getInt8() accountDetailRecord.maxAvatars = di.getInt32() accountDetailRecord.numFamilyMembers = di.getInt16() accountDetailRecord.familyMembers = [] for i in range(accountDetailRecord.numFamilyMembers): accountDetailRecord.familyMembers.append(di.getInt32()) logoutReason = di.getInt32() # Now retrieve the subscription information accountDetailRecord.numSubs = di.getUint16() for i in range(accountDetailRecord.numSubs): subDetailRecord = SubDetailRecord() subDetailRecord.subId = di.getUint32() subDetailRecord.subOwnerId = di.getUint32() subDetailRecord.subName = di.getString() subDetailRecord.subActive = di.getString() access = di.getString() if access == "VELVET": access = OTPGlobals.AccessVelvetRope elif access == "FULL": access = OTPGlobals.AccessFull else: access = OTPGlobals.AccessUnknown subDetailRecord.subAccess = access subDetailRecord.subLevel = di.getUint8() subDetailRecord.subNumAvatars = di.getUint8() subDetailRecord.subNumConcur = di.getUint8() subDetailRecord.subFounder = (di.getString() == "YES") # Add this subscription to the dict on the account record accountDetailRecord.subDetails[subDetailRecord.subId] = subDetailRecord # How many avatar slots total do you get in this game? accountDetailRecord.maxAvatarSlots = di.getInt8() assert self.notify.debug("accountDetailRecord: %s" % accountDetailRecord) if priorAccount: # Send any previous account offline self.accountOffline(priorAccount) pass if newAccount: # Set up the new guy self.accountOnline(newAccount, accountDetailRecord) @report(types = ['args'], dConfigParam = 'avatarmgr') def handleAvatarUsage(self, di): priorAvatar = di.getUint32() newAvatar = di.getUint32() if priorAvatar == 0 and newAvatar == 0: assert self.notify.debug("priorAvatar==0 and newAvatar==0, ignoring avatarUsage message") return newAvatarType = di.getUint16() accountId = di.getUint32() openChatEnabled = di.getString() createFriendsWithChat = di.getString() chatCodeCreation = di.getString() piratesAccess = di.getString() familyAccountId = di.getInt32() playerAccountId = di.getInt32() playerName = di.getString() playerNameApproved = di.getInt8() maxAvatars = di.getInt32() numFamilyMembers = di.getInt16() familyMembers = [] for i in range(numFamilyMembers): familyMembers.append(di.getInt32()) if openChatEnabled == "YES": openChatEnabled = 1 else: openChatEnabled = 0 if priorAvatar: # Send any previous avatar offline self.avatarOffline(accountId, priorAvatar) pass if newAvatar: # Set up the new guy self.avatarOnline(newAvatar, newAvatarType, playerAccountId, playerName, playerNameApproved, openChatEnabled, createFriendsWithChat, chatCodeCreation) @report(types = ['args'], dConfigParam = 'avatarmgr') def accountOnline(self, accountId, accountDetailRecord): self.writeServerEvent('accountOnline', accountId, '') self.onlineAccountDetails[accountId] = accountDetailRecord messenger.send('accountOnline', [accountId]) @report(types = ['args'], dConfigParam = 'avatarmgr') def accountOffline(self, accountId): self.writeServerEvent('accountOffline', accountId, '') self.onlineAccountDetails.pop(accountId, None) self.onlinePlayers.pop(accountId, None) messenger.send('accountOffline', [accountId]) @report(types = ['args'], dConfigParam = 'avatarmgr') def getAccountDetails(self, accountId): return self.onlineAccountDetails.get(accountId) @report(types = ['args'], dConfigParam = 'avatarmgr') def isAccountOnline(self, accountId): return accountId in self.onlineAccountDetails @report(types = ['args'], dConfigParam = 'avatarmgr') def isAvatarOnline(self, avatarId): return avatarId in self.onlineAvatars @report(types = ['args'], dConfigParam = 'avatarmgr') def getAvatarAccountOnline(self, avatarId): return self.onlineAvatars.get(avatarId, 0) @report(types = ['args'], dConfigParam = 'avatarmgr') def getAccountOnlineAvatar(self, accountId): return self.onlinePlayers.get(accountId, 0) @report(types = ['args'], dConfigParam = 'avatarmgr') def checkAccountId(self, accountId): if not accountId: # SUSPICIOUS self.notify.warning("Bogus accountId: %s" % accountId) self.writeServerEvent('suspicious', accountId, 'bogus accountId in OtpAvatarManagerUD') elif not self.isAccountOnline(accountId): # SUSPICIOUS self.notify.warning("Got request from account not online: %s" % accountId) self.writeServerEvent('suspicious', accountId, 'request from offline account in OtpAvatarManagerUD') else: # Everything checks out return True return False @report(types = ['args'], dConfigParam = 'avatarmgr') def avatarOnline(self, avatarId, avatarType, accountId, playerName, playerNameApproved, openChatEnabled, createFriendsWithChat, chatCodeCreation): self.writeServerEvent('avatarOnline', avatarId, '%s|%s|%s|%s|%s|%s' % ( accountId, playerName, playerNameApproved, openChatEnabled, createFriendsWithChat, chatCodeCreation)) self.onlineAvatars[avatarId] = accountId self.onlinePlayers[accountId] = avatarId simpleInfo = [avatarId, avatarType] fullInfo = [avatarId, accountId, playerName, playerNameApproved, openChatEnabled, createFriendsWithChat, chatCodeCreation] # necessary for local UD manager objects messenger.send("avatarOnline", simpleInfo) messenger.send("avatarOnlinePlusAccountInfo", fullInfo) pass @report(types = ['args'], dConfigParam = 'avatarmgr') def avatarOffline(self, accountId, avatarId): self.writeServerEvent('avatarOffline', avatarId, '') self.onlinePlayers.pop(accountId, None) self.onlineAvatars.pop(avatarId, None) # necessary for local UD manager objects messenger.send("avatarOffline", [avatarId]) pass ################################### # Assumed Obsolete as of 6/29/09 # # If you're reading this and there # haven't been any strange UD crashes # here lately, you can probably delete # the next few functions. ################################### def _addObject(self, context, distributedObject): """ Handle a new distributed object arriving by adding it to the cache calling self.handleGotDo(). """ assert False, 'JCW: Testing for obsolete functions. If this crashes, let Josh know' doId=distributedObject.getDoId() assert doId not in self.doId2doCache if doId not in self.doId2doCache: self.doId2doCache[doId]=distributedObject self.handleGotDo(distributedObject) def handleGotDo(self, distributedObject): """ This allows derived classes to override the handling of new distributed objects arriving in the cache. By default, this will loop through the pending calls for that object and make the function calls. It will also remove the handled calls from the pending set. """ assert False, 'JCW: Testing for obsolete functions. If this crashes, let Josh know' assert doId in self.doId2doCache pending=self.pending.get(doId) if pending is not None: del self.pending[doId] for i in pending: i[0](*i[2]) def deleteObject(self, doId): """ Ask for the object to be removed from the private distributed object cache. """ assert False, 'JCW: Testing for obsolete functions. If this crashes, let Josh know' if self.doId2doCache.had_key(doId): self.unregisterForChannel(doId) #self.deleteObject(doId) del self.doId2doCache[doId] #HACK: self.unregisterForChannel(doId) AIRepository.deleteObject(self.doId) def uniqueName(self, desc): return desc if __dev__: """ Early warning system for unsupported use of the Uberdog Repository """ def deleteObjects(self): assert 0 def createDistrict(self, districtId, districtName): assert 0 def deleteDistrict(self, districtId): assert 0 def enterDistrictReset(self): assert 0 def exitDistrictReset(self): assert 0
class MakeAToon: MSG_BADNAME = 'Sorry, that name will not work.' def __init__(self): self.toonMade = 0 self.slot = -1 self.currentShop = None self.currentHead = 0 self.currentTorso = 0 self.currentLeg = 0 self.currentShirt = 0 self.currentShorts = 0 self.shirt1Path = 'phase_3/maps/desat_shirt_1.jpg' self.shirt2Path = 'phase_3/maps/desat_shirt_2.jpg' self.sleeve1Path = 'phase_3/maps/desat_sleeve_1.jpg' self.sleeve2Path = 'phase_3/maps/desat_sleeve_2.jpg' self.skirt1Path = 'phase_3/maps/desat_skirt_1.jpg' self.short1Path = 'phase_3/maps/desat_shorts_1.jpg' self.short2Path = 'phase_3/maps/desat_shorts_2.jpg' self.currentShirtTex = self.shirt1Path self.currentSleeveTex = self.sleeve1Path self.currentShortTex = self.short1Path self.toonName = None self.matFSM = ClassicFSM('MakeAToon', [State('off', self.enterOff, self.exitOff), State('genderShop', self.enterGenderShop, self.exitGenderShop, ['exit', 'off', 'bodyShop']), State('bodyShop', self.enterBodyShop, self.exitBodyShop, ['exit', 'off', 'genderShop', 'colorShop']), State('colorShop', self.enterColorShop, self.exitColorShop, ['exit', 'off', 'bodyShop', 'clothShop']), State('clothShop', self.enterClothShop, self.exitClothShop, ['exit', 'off', 'colorShop', 'nameShop']), State('nameShop', self.enterNameShop, self.exitNameShop, ['exit', 'off', 'clothShop', 'done']), State('exit', self.enterExit, self.exitExit)], 'off', 'off') self.matFSM.enterInitialState() return def enterOff(self): pass def exitOff(self): pass def loadEnviron(self): base.camLens.setFov(CIGlobals.OriginalCameraFov) camera.setPos(-4.77, -17.47, 3.3) camera.setH(344.05) self.mat_gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui.bam') self.cat_gui = loader.loadModel('phase_3/models/gui/create_a_toon_gui.bam') self.nameGui = loader.loadModel('phase_3/models/gui/nameshop_gui.bam') self.namePanel = self.nameGui.find('**/typeNamePanel') self.namePanel.reparentTo(hidden) self.namePanel.setScale(0.6) self.room = loader.loadModel('phase_3/models/makeatoon/tt_m_ara_mat_room.bam') self.floor = self.room.find('**/floor') self.floor.reparentTo(render) self.bg = self.room.find('**/background') self.bg.reparentTo(render) self.bg.setY(1.625) self.genderRoom = self.room.find('**/genderAll') self.genderRoom.reparentTo(hidden) self.bodyRoom = self.room.find('**/bodyAll') self.bodyRoom.reparentTo(hidden) self.colorRoom = self.room.find('**/colorAll') self.colorRoom.reparentTo(hidden) self.clothRoom = self.room.find('**/cothAll') self.clothRoom.reparentTo(hidden) self.nameRoom = self.room.find('**/nameAll') self.nameRoom.reparentTo(hidden) self.desatShirt1 = loader.loadTexture(self.shirt1Path) self.desatShirt2 = loader.loadTexture(self.shirt2Path) self.desatSleeve1 = loader.loadTexture(self.sleeve1Path) self.desatSleeve2 = loader.loadTexture(self.sleeve2Path) self.desatSkirt1 = loader.loadTexture(self.skirt1Path) self.desatShorts1 = loader.loadTexture(self.short1Path) self.desatShorts2 = loader.loadTexture(self.short2Path) self.spotlight = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_spotlight.bam') self.spotlight.setR(90) self.spotlight.setScale(0.6, 0.8, 0.8) self.spotlight.setColor(1, 1, 1, 0.3) self.spotlight_img = OnscreenImage(image=self.spotlight) self.toonGen = ToonGenerator(self) self.music = base.loadMusic('phase_3/audio/bgm/create_a_toon.mid') base.playMusic(self.music, volume=1.0, looping=1) def setSlot(self, slot): self.slot = slot def getSlot(self): return self.slot def __handleNextShop(self): self.okBtn.hide() self.nextBtn.hide() self.exitBtn.hide() self.backBtn.hide() self.nextBtn.hide() self.setNextShop(nextShops[self.currentShop]) def __handlePrevShop(self): self.okBtn.hide() self.nextBtn.hide() self.exitBtn.hide() self.backBtn.hide() self.nextBtn.hide() self.setPrevShop(prevShops[self.currentShop]) def __handleExit(self, direction): self.okBtn.hide() self.nextBtn.hide() self.exitBtn.hide() self.backBtn.hide() self.nextBtn.hide() base.transitions.fadeOut(0.5) Sequence(Wait(0.51), Func(self.exitMakeAToon, direction)).start() def exitMakeAToon(self, direction): self.matFSM.request('exit', enterArgList=[direction]) def finishedMakeAToon(self, textEntered = None): self.toonName = self.nameEntry.get() if self.toonName.isspace() or len(self.toonName) == 0: self.badNameDialog = Dialog.GlobalDialog(message=self.MSG_BADNAME, doneEvent='badNameAck', style=Dialog.Ok) base.acceptOnce('badNameAck', self.__handleBadNameAck) self.badNameDialog.show() return self.__handleExit('finished') def __handleBadNameAck(self): self.badNameDialog.cleanup() del self.badNameDialog def isAvailable(self): return True def setNextShop(self, shop): if shop == 'body': Sequence(Wait(0.21), Func(self.matFSM.request, 'bodyShop')).start() elif shop == 'color': Sequence(Wait(0.21), Func(self.matFSM.request, 'colorShop')).start() elif shop == 'cloth': Sequence(Wait(0.21), Func(self.matFSM.request, 'clothShop')).start() elif shop == 'name': Sequence(Wait(0.21), Func(self.matFSM.request, 'nameShop')).start() self.fade() def setPrevShop(self, shop): if shop == 'gender': Sequence(Wait(0.21), Func(self.matFSM.request, 'genderShop')).start() elif shop == 'body': Sequence(Wait(0.21), Func(self.matFSM.request, 'bodyShop')).start() elif shop == 'color': Sequence(Wait(0.21), Func(self.matFSM.request, 'colorShop')).start() elif shop == 'cloth': Sequence(Wait(0.21), Func(self.matFSM.request, 'clothShop')).start() self.fade() def exitColorShop(self): self.nextAllColorBtn.destroy() self.prevAllColorBtn.destroy() self.nextHeadColorBtn.destroy() self.prevHeadColorBtn.destroy() self.nextTorsoColorBtn.destroy() self.prevTorsoColorBtn.destroy() self.nextLegColorBtn.destroy() self.prevLegColorBtn.destroy() self.colorRoom.reparentTo(hidden) del self.nextAllColorBtn del self.prevAllColorBtn del self.nextHeadColorBtn del self.prevHeadColorBtn del self.nextTorsoColorBtn del self.prevTorsoColorBtn del self.nextLegColorBtn del self.prevLegColorBtn def load(self): self.exitBtn = DirectButton(text=('', 'Exit', 'Exit', ''), text_scale=0.08, text_shadow=(0, 0, 0, 1), text_fg=(1, 1, 1, 1), text_pos=(0, 0.115), geom=(self.mat_gui.find('**/tt_t_gui_mat_closeUp'), self.mat_gui.find('**/tt_t_gui_mat_closeDown'), self.mat_gui.find('**/tt_t_gui_mat_closeUp'), self.mat_gui.find('**/tt_t_gui_mat_closeUp')), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(0.2, 0.2, 0.2), geom0_scale=0.6, geom1_scale=0.65, geom2_scale=0.65, geom3_scale=0.6, command=self.__handleExit, extraArgs=['quit'], parent=base.a2dBottomLeft) self.exitBtn.setBin('gui-popup', 60) self.okBtn = DirectButton(text=('', 'Ready', 'Ready', ''), text_scale=0.08, text_shadow=(0, 0, 0, 1), text_fg=(1, 1, 1, 1), text_pos=(0, 0.115), geom=(self.mat_gui.find('**/tt_t_gui_mat_okUp'), self.mat_gui.find('**/tt_t_gui_mat_okDown'), self.mat_gui.find('**/tt_t_gui_mat_okUp'), self.mat_gui.find('**/tt_t_gui_mat_okUp')), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(-0.2, 0.2, 0.2), geom0_scale=0.6, geom1_scale=0.65, geom2_scale=0.65, geom3_scale=0.6, command=self.finishedMakeAToon, parent=base.a2dBottomRight) self.okBtn.hide() self.okBtn.setBin('gui-popup', 60) self.nextBtn = DirectButton(text=('', 'Next', 'Next', ''), text_scale=0.08, text_shadow=(0, 0, 0, 1), text_fg=(1, 1, 1, 1), text_pos=(0, 0.115), geom=(self.mat_gui.find('**/tt_t_gui_mat_nextUp'), self.mat_gui.find('**/tt_t_gui_mat_nextDown'), self.mat_gui.find('**/tt_t_gui_mat_nextUp'), self.mat_gui.find('**/tt_t_gui_mat_nextDisabled')), relief=None, pos=(-0.2, 0.2, 0.2), geom0_scale=0.3, geom1_scale=0.35, geom2_scale=0.35, geom3_scale=0.3, command=self.__handleNextShop, parent=base.a2dBottomRight) self.nextBtn.setBin('gui-popup', 60) self.backBtn = DirectButton(text=('', 'Back', 'Back', ''), text_scale=0.08, text_shadow=(0, 0, 0, 1), text_fg=(1, 1, 1, 1), text_pos=(0, 0.115), geom=(self.mat_gui.find('**/tt_t_gui_mat_nextUp'), self.mat_gui.find('**/tt_t_gui_mat_nextDown'), self.mat_gui.find('**/tt_t_gui_mat_nextUp'), self.mat_gui.find('**/tt_t_gui_mat_nextDisabled')), relief=None, pos=(-0.4, 0.2, 0.2), geom3_color=Vec4(0.5, 0.5, 0.5, 0.75), geom0_scale=(-0.3, 0.3, 0.3), geom1_scale=(-0.35, 0.35, 0.35), geom2_scale=(-0.35, 0.35, 0.35), geom3_scale=(-0.3, 0.3, 0.3), command=self.__handlePrevShop, parent=base.a2dBottomRight) self.backBtn.setBin('gui-popup', 60) return def enterNameShop(self): self.okBtn.show() self.backBtn.show() self.exitBtn.show() base.transitions.fadeIn(0) self.currentShop = 'name' self.nameRoom.reparentTo(render) self.setTitle('Choose Your Name', 'yellow') self.spotlight_img.setX(0.55) self.spotlight_img.setZ(-0.08) self.namePanelFrame = DirectFrame(pos=(-0.4, 0, 0)) self.namePanel.reparentTo(self.namePanelFrame) self.nameEntry = DirectEntry(parent=self.namePanelFrame, pos=(0.013, 0, 0.26), width=10, numLines=2, scale=0.05, text_align=TextNode.ACenter, relief=None, focus=1, command=self.finishedMakeAToon) self.toonGen.setToonPosForNameShop() return def exitNameShop(self): self.nameRoom.reparentTo(hidden) self.namePanel.setX(0) self.namePanel.reparentTo(hidden) self.nameEntry.destroy() del self.nameEntry self.toonGen.setToonPosForGeneralShop() if hasattr(self, 'badNameDialog'): self.badNameDialog.cleanup() del self.badNameDialog def enterGenderShop(self): self.nextBtn.show() self.exitBtn.show() self.backBtn.show() base.transitions.fadeIn(0) self.currentShop = 'gender' self.genderRoom.reparentTo(render) self.setTitle('Choose Boy Or Girl', 'yellow') self.boyBtn = DirectButton(text=('', 'Boy', 'Boy', ''), text_scale=0.08, text_shadow=(0, 0, 0, 1), text_fg=(1, 1, 1, 1), text_pos=(0, 0.19), geom=(self.mat_gui.find('**/tt_t_gui_mat_boyUp'), self.mat_gui.find('**/tt_t_gui_mat_boyDown'), self.mat_gui.find('**/tt_t_gui_mat_boyUp'), self.mat_gui.find('**/tt_t_gui_mat_boyDown')), relief=None, pos=(-0.45, -0.8, -0.8), geom0_scale=0.6, geom1_scale=0.7, geom2_scale=0.7, geom3_scale=0.6, command=self.generateToon, extraArgs=['boy']) self.girlBtn = DirectButton(text=('', 'Girl', 'Girl', ''), text_scale=0.08, text_shadow=(0, 0, 0, 1), text_fg=(1, 1, 1, 1), text_pos=(0, 0.19), geom=(self.mat_gui.find('**/tt_t_gui_mat_girlUp'), self.mat_gui.find('**/tt_t_gui_mat_girlDown'), self.mat_gui.find('**/tt_t_gui_mat_girlUp'), self.mat_gui.find('**/tt_t_gui_mat_girlDown')), relief=None, pos=(0.45, -0.8, -0.8), geom0_scale=0.6, geom1_scale=0.7, geom2_scale=0.7, geom3_scale=0.6, command=self.generateToon, extraArgs=['girl']) if not self.toonMade: self.nextBtn['state'] = DGG.DISABLED self.backBtn['state'] = DGG.DISABLED return def exitGenderShop(self): self.boyBtn.destroy() self.girlBtn.destroy() self.genderRoom.reparentTo(hidden) del self.boyBtn del self.girlBtn def enterBodyShop(self): self.nextBtn.show() self.exitBtn.show() self.backBtn.show() base.transitions.fadeIn(0) self.currentShop = 'body' self.bodyRoom.reparentTo(render) self.setTitle('Choose Your Type', 'sea-green') self.nextHeadBtn = DirectButton(text='Head', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(-0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(0.45, 0.1, 0.1), command=self.nextHead) self.prevHeadBtn = DirectButton(text='Head', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom_scale=(-1, 1, 1), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(-0.5, 0.1, 0.1), command=self.prevHead) self.nextTorsoBtn = DirectButton(text='Body', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(-0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(0.45, -0.2, -0.2), command=self.nextTorso) self.prevTorsoBtn = DirectButton(text='Body', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom_scale=(-1, 1, 1), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(-0.5, -0.2, -0.2), command=self.prevTorso) self.nextLegBtn = DirectButton(text='Legs', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(-0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(0.45, -0.5, -0.5), command=self.nextLeg) self.prevLegBtn = DirectButton(text='Legs', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom_scale=(-1, 1, 1), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(-0.5, -0.5, -0.5), command=self.prevLeg) self.currentHead = self.toonGen.toon.head self.currentTorso = self.toonGen.toon.torso self.currentLeg = self.toonGen.toon.legs self.updateBodyShopButtons() return def updateBodyShopButtons(self): if self.currentHead == '2' and self.toonGen.toon.animal == 'cat': self.prevHeadBtn['state'] = DGG.NORMAL elif self.currentHead == '4' and self.toonGen.toon.animal == 'duck': self.nextHeadBtn['state'] = DGG.DISABLED elif self.currentHead == '1' and self.toonGen.toon.animal == 'cat': self.prevHeadBtn['state'] = DGG.DISABLED elif self.currentHead == '3' and self.toonGen.toon.animal == 'duck': self.nextHeadBtn['state'] = DGG.NORMAL if self.currentTorso == 'dgm_shorts' and self.toonGen.toon.gender == 'boy' or self.currentTorso == 'dgm_skirt' and self.toonGen.toon.gender == 'girl': self.prevTorsoBtn['state'] = DGG.NORMAL elif self.currentTorso == 'dgl_shorts' and self.toonGen.toon.gender == 'boy' or self.currentTorso == 'dgl_skirt' and self.toonGen.toon.gender == 'girl': self.nextTorsoBtn['state'] = DGG.DISABLED elif self.currentTorso == 'dgs_shorts' and self.toonGen.toon.gender == 'boy' or self.currentTorso == 'dgs_skirt' and self.toonGen.toon.gender == 'girl': self.prevTorsoBtn['state'] = DGG.DISABLED elif self.currentTorso == 'dgm_shorts' and self.toonGen.toon.gender == 'boy' or self.currentTorso == 'dgm_skirt' and self.toonGen.toon.gender == 'girl': self.nextTorsoBtn['state'] = DGG.NORMAL if self.currentLeg == 'dgm': self.prevLegBtn['state'] = DGG.NORMAL elif self.currentLeg == 'dgl': self.nextLegBtn['state'] = DGG.DISABLED elif self.currentLeg == 'dgs': self.prevLegBtn['state'] = DGG.DISABLED elif self.currentLeg == 'dgm': self.nextLegBtn['state'] = DGG.NORMAL self.backBtn['state'] = DGG.NORMAL def nextHead(self): head = self.toonGen.getNextHead() print head newAnimal = None if self.toonGen.toon.animal == 'dog' and head == '00' or self.toonGen.toon.animal == 'cat' and head == '04' or self.toonGen.toon.animal != 'dog' and head == '00': newAnimal = self.toonGen.getNextAnimal() if newAnimal == '00': self.nextHeadBtn['state'] = DGG.DISABLED return self.prevHeadBtn['state'] = DGG.NORMAL self.toonGen.toon.head = self.toonGen.toon.headDNA2head[head] if newAnimal != None: self.toonGen.toon.animal = self.toonGen.toon.animalDNA2animal[newAnimal] self.toonGen.generateDNAStrandWithCurrentStyle() return def prevHead(self): head = self.toonGen.getPrevHead() newAnimal = None if self.toonGen.toon.animal == 'duck' and head == '01' or self.toonGen.toon.animal == 'bear' and head == '07' or self.toonGen.toon.animal == 'dog' and head == '03' or self.toonGen.toon.animal != 'dog' and head == '03': newAnimal = self.toonGen.getPrevAnimal() if newAnimal == '08': self.prevHeadBtn['state'] = DGG.DISABLED return self.nextHeadBtn['state'] = DGG.NORMAL self.toonGen.toon.head = self.toonGen.toon.headDNA2head[head] if newAnimal != None: self.toonGen.toon.animal = self.toonGen.toon.animalDNA2animal[newAnimal] self.toonGen.generateDNAStrandWithCurrentStyle() return def nextTorso(self): newTorso = self.toonGen.getNextTorso() self.toonGen.toon.torso = self.toonGen.toon.torsoDNA2torso[newTorso] self.toonGen.generateDNAStrandWithCurrentStyle() self.updateTorsoButtons(1) def updateTorsoButtons(self, direction): gender = self.toonGen.toon.getGender() if direction == 1: nextNewTorso = self.toonGen.getNextTorso() if nextNewTorso == '00' and gender == 'boy' or nextNewTorso == '03' and gender == 'girl': self.nextTorsoBtn['state'] = DGG.DISABLED self.prevTorsoBtn['state'] = DGG.NORMAL elif direction == 0: nextNewTorso = self.toonGen.getPrevTorso() if nextNewTorso == '02' and gender == 'boy' or nextNewTorso == '05' and gender == 'girl': self.prevTorsoBtn['state'] = DGG.DISABLED self.nextTorsoBtn['state'] = DGG.NORMAL def prevTorso(self): newTorso = self.toonGen.getPrevTorso() self.toonGen.toon.torso = self.toonGen.toon.torsoDNA2torso[newTorso] self.toonGen.generateDNAStrandWithCurrentStyle() self.updateTorsoButtons(0) def nextLeg(self): newLegs = self.toonGen.getNextLeg() self.toonGen.toon.legs = self.toonGen.toon.legDNA2leg[newLegs] self.toonGen.generateDNAStrandWithCurrentStyle() self.updateLegButtons(1) def updateLegButtons(self, direction): if direction == 1: nextNewLeg = self.toonGen.getNextLeg() if nextNewLeg == '00': self.nextLegBtn['state'] = DGG.DISABLED self.prevLegBtn['state'] = DGG.NORMAL elif direction == 0: nextNewLeg = self.toonGen.getPrevLeg() if nextNewLeg == '02': self.prevLegBtn['state'] = DGG.DISABLED self.nextLegBtn['state'] = DGG.NORMAL def prevLeg(self): newLegs = self.toonGen.getPrevLeg() self.toonGen.toon.legs = self.toonGen.toon.legDNA2leg[newLegs] self.toonGen.generateDNAStrandWithCurrentStyle() self.updateLegButtons(0) def exitBodyShop(self): self.nextHeadBtn.destroy() self.prevHeadBtn.destroy() self.nextTorsoBtn.destroy() self.prevTorsoBtn.destroy() self.nextLegBtn.destroy() self.prevLegBtn.destroy() self.bodyRoom.reparentTo(hidden) del self.nextHeadBtn del self.prevHeadBtn del self.nextTorsoBtn del self.prevTorsoBtn del self.nextLegBtn del self.prevLegBtn def enterColorShop(self): self.nextBtn.show() self.exitBtn.show() self.backBtn.show() base.transitions.fadeIn(0) self.currentShop = 'color' self.colorRoom.reparentTo(render) self.setTitle('Choose Your Color', 'light-blue') self.nextAllColorBtn = DirectButton(text='Toon', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(-0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom_scale=(1, 1, 1), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, scale=1.3, pos=(0.45, 0.5, 0.5), command=self.nextAllColor) self.prevAllColorBtn = DirectButton(text='Toon', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom_scale=(-1, 1, 1), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, scale=1.3, pos=(-0.5, 0.5, 0.5), command=self.prevAllColor) self.nextHeadColorBtn = DirectButton(text='Head', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(-0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(0.45, 0.1, 0.1), command=self.nextHeadColor) self.prevHeadColorBtn = DirectButton(text='Head', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom_scale=(-1, 1, 1), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(-0.5, 0.1, 0.1), command=self.prevHeadColor) self.nextTorsoColorBtn = DirectButton(text='Body', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(-0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(0.45, -0.2, -0.2), command=self.nextTorsoColor) self.prevTorsoColorBtn = DirectButton(text='Body', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom_scale=(-1, 1, 1), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(-0.5, -0.2, -0.2), command=self.prevTorsoColor) self.nextLegColorBtn = DirectButton(text='Legs', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(-0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(0.45, -0.5, -0.5), command=self.nextLegColor) self.prevLegColorBtn = DirectButton(text='Legs', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom_scale=(-1, 1, 1), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(-0.5, -0.5, -0.5), command=self.prevLegColor) self.currentColor = self.toonGen.toon.headcolor self.currentHeadColor = self.toonGen.toon.headcolor self.currentTorsoColor = self.toonGen.toon.torsocolor self.currentLegColor = self.toonGen.toon.legcolor self.updateColorShopButtons() return def setColorShopButtonsNormal(self): self.prevAllColorBtn['state'] = DGG.NORMAL self.prevHeadColorBtn['state'] = DGG.NORMAL self.prevTorsoColorBtn['state'] = DGG.NORMAL self.prevLegColorBtn['state'] = DGG.NORMAL self.nextAllColorBtn['state'] = DGG.NORMAL self.nextHeadColorBtn['state'] = DGG.NORMAL self.nextTorsoColorBtn['state'] = DGG.NORMAL self.nextLegColorBtn['state'] = DGG.NORMAL def updateColorShopButtons(self): self.setColorShopButtonsNormal() if self.toonGen.toon.color2colorDNA[self.currentColor] == '01': self.prevAllColorBtn['state'] = DGG.NORMAL self.prevHeadColorBtn['state'] = DGG.NORMAL self.prevTorsoColorBtn['state'] = DGG.NORMAL self.prevLegColorBtn['state'] = DGG.NORMAL elif self.toonGen.toon.color2colorDNA[self.currentColor] == '26': self.nextAllColorBtn['state'] = DGG.DISABLED self.nextHeadColorBtn['state'] = DGG.DISABLED self.nextTorsoColorBtn['state'] = DGG.DISABLED self.nextLegColorBtn['state'] = DGG.DISABLED elif self.toonGen.toon.color2colorDNA[self.currentColor] == '00': self.prevAllColorBtn['state'] = DGG.DISABLED self.prevHeadColorBtn['state'] = DGG.DISABLED self.prevTorsoColorBtn['state'] = DGG.DISABLED self.prevLegColorBtn['state'] = DGG.DISABLED elif self.toonGen.toon.color2colorDNA[self.currentColor] == '25': self.nextAllColorBtn['state'] = DGG.NORMAL self.nextHeadColorBtn['state'] = DGG.NORMAL self.nextTorsoColorBtn['state'] = DGG.NORMAL self.nextLegColorBtn['state'] = DGG.NORMAL def updateColorShopButtonsDir(self, direction): self.setColorShopButtonsNormal() if direction == 1: nextNewHColor = self.toonGen.getNextColor('head') nextNewTColor = self.toonGen.getNextColor('torso') nextNewLColor = self.toonGen.getNextColor('legs') if nextNewHColor == '00': self.nextAllColorBtn['state'] = DGG.DISABLED self.nextHeadColorBtn['state'] = DGG.DISABLED if nextNewTColor == '00': self.nextTorsoColorBtn['state'] = DGG.DISABLED if nextNewLColor == '00': self.nextLegColorBtn['state'] = DGG.DISABLED elif direction == 0: nextNewHColor = self.toonGen.getPrevColor('head') nextNewTColor = self.toonGen.getPrevColor('torso') nextNewLColor = self.toonGen.getPrevColor('legs') if nextNewHColor == '26': self.prevAllColorBtn['state'] = DGG.DISABLED self.prevHeadColorBtn['state'] = DGG.DISABLED if nextNewTColor == '26': self.prevTorsoColorBtn['state'] = DGG.DISABLED if nextNewLColor == '26': self.prevLegColorBtn['state'] = DGG.DISABLED def nextAllColor(self): color = self.toonGen.getNextColor('all') self.toonGen.toon.headcolor = self.toonGen.toon.colorDNA2color[color] self.toonGen.toon.torsocolor = self.toonGen.toon.colorDNA2color[color] self.toonGen.toon.legcolor = self.toonGen.toon.colorDNA2color[color] self.toonGen.toon.setToonColor() self.updateColorShopButtonsDir(1) def prevAllColor(self): color = self.toonGen.getPrevColor('all') self.toonGen.toon.headcolor = self.toonGen.toon.colorDNA2color[color] self.toonGen.toon.torsocolor = self.toonGen.toon.colorDNA2color[color] self.toonGen.toon.legcolor = self.toonGen.toon.colorDNA2color[color] self.toonGen.toon.setToonColor() self.updateColorShopButtonsDir(0) def nextHeadColor(self): color = self.toonGen.getNextColor('head') self.toonGen.toon.headcolor = self.toonGen.toon.colorDNA2color[color] self.toonGen.toon.setToonColor() self.updateColorShopButtonsDir(1) def prevHeadColor(self): color = self.toonGen.getPrevColor('head') self.toonGen.toon.headcolor = self.toonGen.toon.colorDNA2color[color] self.toonGen.toon.setToonColor() self.updateColorShopButtonsDir(0) def nextTorsoColor(self): color = self.toonGen.getNextColor('torso') self.toonGen.toon.torsocolor = self.toonGen.toon.colorDNA2color[color] self.toonGen.toon.setToonColor() self.updateColorShopButtonsDir(1) def prevTorsoColor(self): color = self.toonGen.getPrevColor('torso') self.toonGen.toon.torsocolor = self.toonGen.toon.colorDNA2color[color] self.toonGen.toon.setToonColor() self.updateColorShopButtonsDir(0) def nextLegColor(self): color = self.toonGen.getNextColor('legs') self.toonGen.toon.legcolor = self.toonGen.toon.colorDNA2color[color] self.toonGen.toon.setToonColor() self.updateColorShopButtonsDir(1) def prevLegColor(self): color = self.toonGen.getPrevColor('legs') self.toonGen.toon.legcolor = self.toonGen.toon.colorDNA2color[color] self.toonGen.toon.setToonColor() self.updateColorShopButtonsDir(0) def nextShirt(self): newShirt, newSleeve = self.toonGen.getNextShirtAndSleeve() newColor = self.toonGen.getNextColor('shirt') self.toonGen.toon.shirtColor = self.toonGen.toon.colorDNA2color[newColor] self.toonGen.toon.sleeveColor = self.toonGen.toon.colorDNA2color[newColor] if newShirt != None and newSleeve != None: self.toonGen.toon.shirt = self.toonGen.toon.shirtDNA2shirt[newShirt] self.toonGen.toon.sleeve = self.toonGen.toon.sleeveDNA2sleeve[newSleeve] self.toonGen.toon.setClothes() self.updateClothShopButtonsDir(1) return def prevShirt(self): newShirt, newSleeve = self.toonGen.getPrevShirtAndSleeve() newColor = self.toonGen.getPrevColor('shirt') self.toonGen.toon.shirtColor = self.toonGen.toon.colorDNA2color[newColor] self.toonGen.toon.sleeveColor = self.toonGen.toon.colorDNA2color[newColor] if newShirt != None and newSleeve != None: self.toonGen.toon.shirt = self.toonGen.toon.shirtDNA2shirt[newShirt] self.toonGen.toon.sleeve = self.toonGen.toon.sleeveDNA2sleeve[newSleeve] self.toonGen.toon.setClothes() self.updateClothShopButtonsDir(1) return def updateClothShopButtonsDir(self, direction): self.nextShirtBtn['state'] = DGG.NORMAL self.prevShirtBtn['state'] = DGG.NORMAL self.nextShortsBtn['state'] = DGG.NORMAL self.prevShortsBtn['state'] = DGG.NORMAL if direction == 1: if self.toonGen.getNextShirt() == '00': self.nextShirtBtn['state'] = DGG.DISABLED if self.toonGen.getNextShorts() == '00': self.nextShortsBtn['state'] = DGG.DISABLED if self.toonGen.getPrevShirt() == '22': self.prevShirtBtn['state'] = DGG.DISABLED if self.toonGen.getPrevShorts() == '16': self.prevShortsBtn['state'] = DGG.DISABLED def nextShorts(self): newShorts = self.toonGen.getNextShorts() newColor = self.toonGen.getNextColor('shorts') self.toonGen.toon.shortColor = self.toonGen.toon.colorDNA2color[newColor] if newShorts != None: self.toonGen.toon.shorts = self.toonGen.toon.shortDNA2short[newShorts] self.toonGen.toon.setClothes() self.updateClothShopButtonsDir(1) return def prevShorts(self): newShorts = self.toonGen.getPrevShorts() newColor = self.toonGen.getPrevColor('shorts') self.toonGen.toon.shortColor = self.toonGen.toon.colorDNA2color[newColor] if newShorts != None: self.toonGen.toon.shorts = self.toonGen.toon.shortDNA2short[newShorts] self.toonGen.toon.setClothes() self.updateClothShopButtonsDir(1) return def updateClothes(self): if self.currentShirt > 26: self.currentShirtTex = self.shirt2Path self.currentSleeveTex = self.sleeve2Path else: self.currentShirtTex = self.shirt1Path self.currentSleeveTex = self.sleeve1Path if self.gender == 'boy': if self.currentShorts > 26: self.currentShortTex = self.short2Path else: self.currentShortTex = self.short1Path elif self.gender == 'girl': self.currentShortTex = self.skirt1Path def getToonColors(self): hr, hg, hb, ha = toonColors[self.currentHeadColor] tr, tg, tb, ta = toonColors[self.currentTorsoColor] lr, lg, lb, la = toonColors[self.currentLegColor] return tuple((hr, hg, hb, tr, tg, tb, lr, lg, lb)) def enterClothShop(self): self.nextBtn.show() self.exitBtn.show() self.backBtn.show() base.transitions.fadeIn(0) self.currentShop = 'cloth' self.clothRoom.reparentTo(render) self.setTitle('Choose Your Clothes', 'light-blue') self.nextShirtBtn = DirectButton(text='Shirt', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(-0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(0.45, -0.2, -0.2), command=self.nextShirt) self.prevShirtBtn = DirectButton(text='Shirt', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom_scale=(-1, 1, 1), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(-0.5, -0.2, -0.2), command=self.prevShirt) self.nextShortsBtn = DirectButton(text='Shorts', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(-0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(0.45, -0.5, -0.5), command=self.nextShorts) self.prevShortsBtn = DirectButton(text='Shorts', text_scale=0.06, text_fg=(1, 0, 0, 1), text_pos=(0.03, 0.005), geom=(self.cat_gui.find('**/CrtATn_R_Arrow_UP'), self.cat_gui.find('**/CrtATn_R_Arrow_DN'), self.cat_gui.find('**/CrtATn_R_Arrow_RLVR'), self.cat_gui.find('**/CrtATn_R_Arrow_UP')), geom_scale=(-1, 1, 1), geom3_color=(0.6, 0.6, 0.6, 0.6), relief=None, pos=(-0.5, -0.5, -0.5), command=self.prevShorts) self.updateClothes() if self.currentShirt == 0: self.nextShirtBtn['state'] = DGG.NORMAL self.prevShirtBtn['state'] = DGG.DISABLED elif self.currentShirt == 26: self.nextShirtBtn['state'] = DGG.DISABLED self.prevShirtBtn['state'] = DGG.NORMAL if self.currentShorts == 0: self.nextShortsBtn['state'] = DGG.NORMAL self.prevShortsBtn['state'] = DGG.DISABLED if self.gender == 'boy': if self.currentShorts == 53: self.nextShortsBtn['state'] = DGG.DISABLED self.prevShortsBtn['state'] = DGG.NORMAL elif self.gender == 'girl': if self.currentShorts == 26: self.nextShortsBtn['state'] = DGG.DISABLED self.prevShortsBtn['state'] = DGG.NORMAL return def deleteClothShopTask(self, task): self.deleteClothShop() def exitClothShop(self): self.nextShirtBtn.destroy() self.prevShirtBtn.destroy() self.nextShortsBtn.destroy() self.prevShortsBtn.destroy() self.clothRoom.reparentTo(hidden) del self.nextShirtBtn del self.prevShirtBtn del self.nextShortsBtn del self.prevShortsBtn def generateToon(self, gender): self.gender = gender self.toonGen.generateToon(gender) self.toonMade = 1 self.nextBtn['state'] = DGG.NORMAL def fade(self): base.transitions.fadeOut(0.2) def enterExit(self, direction): if direction == 'finished': self.toonGen.generateDNAStrandWithCurrentStyle() base.transitions.noTransitions() messenger.send('createAToonFinished', [self.toonGen.toon.dnaStrand, self.getSlot(), self.toonName]) return elif direction == 'quit': base.transitions.noTransitions() messenger.send('quitCreateAToon') return else: self.mat_gui.remove() self.cat_gui.remove() self.nameGui.removeNode() self.room.remove() if self.toonMade: self.toonGen.cleanupToon() if self.currentShop is not None: self.backBtn.destroy() self.exitBtn.destroy() if self.currentShop is not None: self.okBtn.destroy() self.nextBtn.destroy() self.title_lbl.destroy() del self.exitBtn del self.nextBtn del self.backBtn del self.okBtn del self.title_lbl self.spotlight_img.destroy() self.spotlight.remove() self.genderRoom.remove() self.bodyRoom.remove() self.colorRoom.remove() self.floor.remove() self.bg.remove() del self.genderRoom del self.bodyRoom del self.colorRoom del self.floor del self.bg del self.mat_gui del self.cat_gui del self.room del self.spotlight_img del self.spotlight del self.nameGui self.toonName = None self.toonMade = 0 self.music.stop() del self.music del self.toonGen base.camLens.setMinFov(CIGlobals.DefaultCameraFov / (4.0 / 3.0)) return def exitExit(self): pass def setTitle(self, title, color): try: self.title_lbl.destroy() except: pass self.title_lbl = DirectLabel(text=title, relief=None, text_scale=0.16, text_font=loader.loadFont('phase_3/models/fonts/MickeyFont.bam'), pos=(0, 0.85, 0.85)) if color == 'yellow': self.title_lbl['text_fg'] = (1, 1, 0, 1) elif color == 'sea-green': self.title_lbl['text_fg'] = (0, 0.8509803921568627, 0.4784313725490196, 1) elif color == 'light-blue': self.title_lbl['text_fg'] = (0, 0.8901960784313725, 1, 1) return
class DistributedBoat(DistributedObject): notify = directNotify.newCategory("DistributedBoat") def __init__(self, cr): DistributedObject.__init__(self, cr) self.fsm = ClassicFSM('DistributedBoat', [ State('off', self.enterOff, self.exitOff), State('eastToWest', self.enterEastToWest, self.exitEastToWest), State('westToEast', self.enterWestToEast, self.exitWestToEast) ], 'off', 'off') self.boat = None self.eastPier = None self.eastPierPath = 'east_pier' self.westPier = None self.westPierPath = 'west_pier' self.pierUpP = 0.0 self.pierDownP = -45.0 self.fogHorn = 'phase_5/audio/sfx/SZ_DD_foghorn.ogg' self.shipBell = 'phase_6/audio/sfx/SZ_DD_shipbell.ogg' self.waterLap = 'phase_6/audio/sfx/SZ_DD_waterlap.ogg' self.dockCreak = 'phase_6/audio/sfx/SZ_DD_dockcreak.ogg' self.eastWest = 'phase_6/paths/dd-e-w.bam' self.westEast = 'phase_6/paths/dd-w-e.bam' self.track = None self.state = None self.animBoat1Track = None self.animBoatTrack = None # Variables that handle the winter collision node. self.crashColl = None self.crashCollNP = None def __handleOnBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPDonaldsBoat) def __handleOffBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPRender) base.localAvatar.setR(0) base.localAvatar.setP(0) def generate(self): DistributedObject.generate(self) self.soundFogHorn = base.audio3d.loadSfx(self.fogHorn) self.soundShipBell = base.audio3d.loadSfx(self.shipBell) self.soundWaterLap = base.audio3d.loadSfx(self.waterLap) self.soundDockCreak = base.audio3d.loadSfx(self.dockCreak) geom = self.cr.playGame.hood.loader.geom self.boatMdl = geom.find('**/*donalds_boat*') self.boat = geom.find("**/ddBoatRoot") self.boatMdl1 = geom.find("**/ddBoatMdl1") base.audio3d.attachSoundToObject(self.soundFogHorn, self.boat) base.audio3d.attachSoundToObject(self.soundShipBell, self.boat) base.audio3d.attachSoundToObject(self.soundWaterLap, self.boat) base.audio3d.attachSoundToObject(self.soundDockCreak, self.boat) self.soundWaterLap.setLoop(True) self.soundWaterLap.play() self.generated() def generated(self): self.eastPier = self.cr.playGame.hood.loader.geom.find( '**/' + self.eastPierPath) self.westPier = self.cr.playGame.hood.loader.geom.find( '**/' + self.westPierPath) base.cr.parentMgr.registerParent(CIGlobals.SPDonaldsBoat, self.boatMdl) self.accept('enterdonalds_boat_floor', self.__handleOnBoat) self.accept('exitdonalds_boat_floor', self.__handleOffBoat) self.d_requestCurrentStateAndTimestamp() self.fsm.enterInitialState() speedFactor = 2 self.animBoatTrack = Sequence( LerpHprInterval(self.boatMdl, duration=1 * speedFactor, hpr=(0, 0, -1), startHpr=(0, 0, 1), blendType='easeInOut'), LerpHprInterval(self.boatMdl, duration=1 * speedFactor, hpr=(0, 0, 1), startHpr=(0, 0, -1), blendType='easeInOut')) import math self.animBoat1Track = Sequence( LerpHprInterval(self.boatMdl1, duration=math.pi * speedFactor, hpr=(0, 1, 0), startHpr=(0, -1, 0), blendType='easeInOut'), LerpHprInterval(self.boatMdl1, duration=math.pi * speedFactor, hpr=(0, -1, 0), startHpr=(0, 1, 0), blendType='easeInOut')) self.animBoat1Track.loop() self.animBoatTrack.loop() if base.cr.holidayManager.getHoliday() == HolidayType.CHRISTMAS: self.boat.setPosHpr(12.73, -1.6, -4.7, 341.57, 350.0, 26.5) self.fsm.request('off') self.crashColl = CollisionSphere(0, 0, 0, 15) self.crashCollNP = self.boat.attachNewNode( CollisionNode('crashed_boat_collision')) self.crashCollNP.node().addSolid(self.crashColl) self.crashCollNP.node().setCollideMask(CIGlobals.WallBitmask) self.crashCollNP.setSz(2) self.crashCollNP.setSx(0.75) self.crashCollNP.setSy(1.25) self.crashCollNP.setPosHpr(2.05, 3.21, 1.66, 8.44, 6.93, 332.61) def disable(self): base.taskMgr.remove(self.uniqueName('__pollBoat')) base.cr.parentMgr.unregisterParent(CIGlobals.SPDonaldsBoat) self.ignore('enterdonalds_boat_floor') self.ignore('exitdonalds_boat_floor') self.fsm.requestFinalState() if self.animBoat1Track: self.animBoat1Track.finish() self.animBoat1Track = None if self.animBoatTrack: self.animBoatTrack.finish() self.animBoatTrack = None if self.crashCollNP: self.crashCollNP.removeNode() del self.crashCollNP del self.crashColl del self.fsm del self.soundFogHorn del self.soundShipBell self.soundWaterLap.stop() del self.soundWaterLap del self.soundDockCreak self.fogHorn = None self.shipBell = None self.waterLap = None self.dockCreak = None self.boat = None self.boatMdl = None self.boatMdl1 = None self.track = None self.pierDownP = None self.pierUpP = None self.eastPier = None self.eastPierPath = None self.westPier = None self.westPierPath = None self.boatPath = None self.westEast = None self.eastWest = None DistributedObject.disable(self) def currentStateAndTimestamp(self, state, timestamp): self.setState(state, timestamp) def d_requestCurrentStateAndTimestamp(self): self.sendUpdate('requestCurrentStateAndTimestamp', []) def setState(self, state, timestamp=None): if timestamp is None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) self.state = state if self.boat and base.cr.holidayManager.getHoliday( ) != HolidayType.CHRISTMAS: self.fsm.request(state, [ts]) def enterEastToWest(self, ts=0): moPath = Mopath.Mopath() moPath.loadFile(self.eastWest) moIval = MopathInterval(moPath, self.boat, blendType='easeInOut') self.track = Parallel( SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.eastPier), moIval, LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierDownP, 0), startHpr=(90, self.pierUpP, 0), blendType='easeInOut'), Sequence( Wait(15.0), Parallel( LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierUpP, 0), startHpr=(-90, self.pierDownP, 0), blendType='easeInOut'), Sequence( Wait(2.0), SoundInterval(self.soundDockCreak, node=self.westPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitEastToWest(self): if self.track: self.track.finish() self.track = None def enterWestToEast(self, ts=0): moPath = Mopath.Mopath() moPath.loadFile(self.westEast) moIval = MopathInterval(moPath, self.boat, blendType='easeInOut') self.track = Parallel( SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.westPier), moIval, LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierDownP, 0), startHpr=(-90, self.pierUpP, 0), blendType='easeInOut'), Sequence( Wait(15.0), Parallel( LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierUpP, 0), startHpr=(90, self.pierDownP, 0), blendType='easeInOut'), Sequence( Wait(2.0), SoundInterval(self.soundDockCreak, node=self.eastPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitWestToEast(self): if self.track: self.track.finish() self.track = None def enterOff(self): pass def exitOff(self): pass
class Toon(Avatar.Avatar, ToonHead, ToonDNA.ToonDNA): def __init__(self, cr, mat = 0): self.cr = cr try: self.Toon_initialized return except: self.Toon_initialized = 1 Avatar.Avatar.__init__(self, mat) ToonDNA.ToonDNA.__init__(self) ToonHead.__init__(self, cr) self.forwardSpeed = 0.0 self.rotateSpeed = 0.0 self.avatarType = CIGlobals.Toon self.track = None self.standWalkRunReverse = None self.playingAnim = None self.tag = None self.money = 0 self.lookAtTrack = None self.portal1 = None self.portal2 = None self.gunAttached = False self.gun = None self.tokenIcon = None self.tokenIconIval = None self.backpack = None self.forcedTorsoAnim = None self.fallSfx = base.audio3d.loadSfx('phase_4/audio/sfx/MG_cannon_hit_dirt.mp3') base.audio3d.attachSoundToObject(self.fallSfx, self) self.eyes = loader.loadTexture('phase_3/maps/eyes.jpg', 'phase_3/maps/eyes_a.rgb') self.myTaskId = random.uniform(0, 1231231232132131231232L) self.closedEyes = loader.loadTexture('phase_3/maps/eyesClosed.jpg', 'phase_3/maps/eyesClosed_a.rgb') self.soundChatBubble = loader.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.mp3') self.shadowCaster = None self.chatSoundDict = {} self.animFSM = ClassicFSM('Toon', [State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('swim', self.enterSwim, self.exitSwim), State('walk', self.enterWalk, self.exitWalk), State('run', self.enterRun, self.exitRun), State('openBook', self.enterOpenBook, self.exitOpenBook), State('readBook', self.enterReadBook, self.exitReadBook), State('closeBook', self.enterCloseBook, self.exitCloseBook), State('teleportOut', self.enterTeleportOut, self.exitTeleportOut), State('teleportIn', self.enterTeleportIn, self.exitTeleportIn), State('died', self.enterDied, self.exitDied), State('fallFWD', self.enterFallFWD, self.exitFallFWD), State('fallBCK', self.enterFallBCK, self.exitFallBCK), State('jump', self.enterJump, self.exitJump), State('leap', self.enterLeap, self.exitLeap), State('laugh', self.enterLaugh, self.exitLaugh), State('happy', self.enterHappyJump, self.exitHappyJump), State('shrug', self.enterShrug, self.exitShrug), State('hdance', self.enterHDance, self.exitHDance), State('wave', self.enterWave, self.exitWave), State('scientistEmcee', self.enterScientistEmcee, self.exitScientistEmcee), State('scientistWork', self.enterScientistWork, self.exitScientistWork), State('scientistGame', self.enterScientistGame, self.exitScientistGame), State('scientistJealous', self.enterScientistJealous, self.exitScientistJealous), State('cringe', self.enterCringe, self.exitCringe), State('conked', self.enterConked, self.exitConked), State('win', self.enterWin, self.exitWin), State('walkBack', self.enterWalkBack, self.exitWalkBack), State('deadNeutral', self.enterDeadNeutral, self.exitDeadNeutral), State('deadWalk', self.enterDeadWalk, self.exitDeadWalk), State('squish', self.enterSquish, self.exitSquish), State('Happy', self.enterHappy, self.exitHappy), State('Sad', self.enterSad, self.exitSad)], 'off', 'off') animStateList = self.animFSM.getStates() self.animFSM.enterInitialState() if not hasattr(base, 'localAvatar') or not base.localAvatar == self: Avatar.Avatar.initializeBodyCollisions(self, self.avatarType, 3, 1) return def enterHappy(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = None self.standWalkRunReverse = (('neutral', 1.0), ('walk', 1.0), ('run', 1.0), ('walk', -1.0)) self.setSpeed(self.forwardSpeed, self.rotateSpeed) return def exitHappy(self): self.standWalkRunReverse = None self.stop() return def enterSad(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'sad' self.standWalkRunReverse = (('dneutral', 1.0), ('dwalk', 1.2), ('dwalk', 1.2), ('dwalk', -1.0)) self.setSpeed(0, 0) def exitSad(self): self.standWalkRunReverse = None self.stop() return def setSpeed(self, forwardSpeed, rotateSpeed): self.forwardSpeed = forwardSpeed self.rotateSpeed = rotateSpeed action = None if self.standWalkRunReverse != None: if forwardSpeed >= CIGlobals.RunCutOff: action = CIGlobals.RUN_INDEX elif forwardSpeed > CIGlobals.WalkCutOff: action = CIGlobals.WALK_INDEX elif forwardSpeed < -CIGlobals.WalkCutOff: action = CIGlobals.REVERSE_INDEX elif rotateSpeed != 0.0: action = CIGlobals.WALK_INDEX else: action = CIGlobals.STAND_INDEX anim, rate = self.standWalkRunReverse[action] if anim != self.playingAnim: self.playingAnim = anim self.stop() self.loop(anim) self.setPlayRate(rate, anim) return action def enterSquish(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'squish' sound = loader.loadSfx('phase_9/audio/sfx/toon_decompress.mp3') lerpTime = 0.1 node = self.getGeomNode().getChild(0) origScale = node.getScale() if hasattr(self, 'uniqueName'): name = self.uniqueName('getSquished') else: name = 'getSquished' self.track = Sequence(LerpScaleInterval(node, lerpTime, VBase3(2, 2, 0.025), blendType='easeInOut'), Wait(1.0), Parallel(Sequence(Wait(0.4), LerpScaleInterval(node, lerpTime, VBase3(1.4, 1.4, 1.4), blendType='easeInOut'), LerpScaleInterval(node, lerpTime / 2.0, VBase3(0.8, 0.8, 0.8), blendType='easeInOut'), LerpScaleInterval(node, lerpTime / 3.0, origScale, blendType='easeInOut')), ActorInterval(self, 'happy', startTime=0.2), SoundInterval(sound)), name=name) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.squishDone, [callback, extraArgs]) self.track.delayDelete = DelayDelete.DelayDelete(self, name) self.track.start(ts) def squishDone(self, callback = None, extraArgs = []): self.__doCallback(callback, extraArgs) def exitSquish(self): if self.track: self.ignore(self.track.getName()) DelayDelete.cleanupDelayDeletes(self.track) self.track.finish() self.track = None self.playingAnim = 'neutral' return def enterDeadNeutral(self, ts = 0, callback = None, extraArgs = []): self.loop('dneutral') def exitDeadNeutral(self): self.stop() def enterDeadWalk(self, ts = 0, callback = None, extraArgs = []): self.loop('dwalk') def exitDeadWalk(self): self.stop() def setBackpack(self, pack): self.backpack = pack def getGhost(self): return 0 def updateChatSoundDict(self): self.chatSoundDict['exclaim'] = base.audio3d.loadSfx(self.getToonAnimalNoise('exclaim')) self.chatSoundDict['question'] = base.audio3d.loadSfx(self.getToonAnimalNoise('question')) self.chatSoundDict['short'] = base.audio3d.loadSfx(self.getToonAnimalNoise('short')) self.chatSoundDict['medium'] = base.audio3d.loadSfx(self.getToonAnimalNoise('med')) self.chatSoundDict['long'] = base.audio3d.loadSfx(self.getToonAnimalNoise('long')) self.chatSoundDict['howl'] = base.audio3d.loadSfx(self.getToonAnimalNoise('howl')) base.audio3d.attachSoundToObject(self.chatSoundDict['exclaim'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['question'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['short'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['medium'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['long'], self.getPart('head')) base.audio3d.attachSoundToObject(self.chatSoundDict['howl'], self.getPart('head')) def ghostOn(self): self.getGeomNode().hide() self.getNameTag().hide() self.getShadow().hide() if self.tokenIcon: self.tokenIcon.hide() self.stashBodyCollisions() def ghostOff(self): self.unstashBodyCollisions() if self.tokenIcon: self.tokenIcon.show() self.getShadow().show() self.getNameTag().show() self.getGeomNode().show() def attachGun(self, gunName): self.detachGun() if gunName == 'pistol': self.gun = loader.loadModel('phase_4/models/props/water-gun.bam') self.gun.reparentTo(self.find('**/def_joint_right_hold')) self.gun.setPos(Point3(0.28, 0.1, 0.08)) self.gun.setHpr(VBase3(85.6, -4.44, 94.43)) self.gunAttached = True elif gunName == 'shotgun': self.gun = loader.loadModel('phase_4/models/props/shotgun.egg') self.gun.setScale(0.75) self.gun.reparentTo(self.find('**/def_joint_right_hold')) self.gun.setPos(Point3(-0.5, -0.2, 0.19)) self.gun.setHpr(Vec3(350, 272.05, 0)) color = random.choice([VBase4(1, 0.25, 0.25, 1), VBase4(0.25, 1, 0.25, 1), VBase4(0.25, 0.25, 1, 1)]) self.gun.setColorScale(color) self.gunAttached = True def detachGun(self): if self.gun and self.gunAttached: self.gun.removeNode() self.gun = None self.gunAttached = False return def stopAnimations(self): if hasattr(self, 'animFSM'): if not self.animFSM.isInternalStateInFlux(): self.animFSM.request('off') else: notify.warning('animFSM in flux, state=%s, not requesting off' % self.animFSM.getCurrentState().getName()) else: notify.warning('animFSM has been deleted') if self.track != None: self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None return def disable(self): try: self.Toon_disabled except: self.Toon_disabled = 1 self.backpack = None self.stopAnimations() self.removeAdminToken() ToonHead.delete(self) self.deleteCurrentToon() self.chatSoundDict = {} return def delete(self): try: self.Toon_deleted except: self.Toon_deleted = 1 del self.animFSM self.forwardSpeed = None self.chatSoundDict = None self.rotateSpeed = None self.avatarType = None self.track = None self.standWalkRunReverse = None self.currentAnim = None self.toon_head = None self.forcedTorsoAnim = None self.toon_torso = None self.toon_legs = None self.gender = None self.headtype = None self.head = None self.legtype = None self.torsotype = None self.hr = None self.hg = None self.hb = None self.tr = None self.tg = None self.tb = None self.lr = None self.lg = None self.lb = None self.shir = None self.shig = None self.shib = None self.shor = None self.shog = None self.shob = None self.shirt = None self.sleeve = None self.short = None self.tag = None self.money = None self.lookAtTrack = None self.portal1 = None self.portal2 = None self.backpack = None self.fallSfx = None self.eyes = None self.myTaskId = None self.closedEyes = None self.soundChatBubble = None self.lastAction = None self.lastState = None self.playingAnim = None Avatar.Avatar.delete(self) return def initCollisions(self): self.collNodePath.setCollideMask(BitMask32(0)) self.collNodePath.node().setFromCollideMask(CIGlobals.WallBitmask) pusher = CollisionHandlerPusher() pusher.setInPattern('%in') pusher.addCollider(self.collNodePath, self) base.cTrav.addCollider(self.collNodePath, pusher) def deleteCurrentToon(self): if self.shadowCaster: self.shadowCaster.clear() self.shadowCaster = None try: self.stopLookAround() self.stopBlink() except: pass self.pupils = [] if 'head' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['head'] if 'torso' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['torso'] if 'legs' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['legs'] self.deleteShadow() self.removePart('head') self.removePart('torso') self.removePart('legs') self.detachGun() return def enterGagShop(self): DirectLabel(text='ENTERED GAG SHOP', relief=None, text_scale=0.08) return def setAdminToken(self, tokenId): tokens = {0: 500} if tokenId in tokens.keys(): icons = loader.loadModel('phase_3/models/props/gm_icons.bam') self.tokenIcon = icons.find('**/access_level_%s' % tokens[tokenId]) self.tokenIcon.reparentTo(self) x = self.getNameTag().getX() y = self.getNameTag().getY() z = self.getNameTag().getZ() self.tokenIcon.setPos(Vec3(x, y, z) + (0, 0, 0.5)) self.tokenIcon.setScale(0.4) self.tokenIconIval = Sequence(LerpHprInterval(self.tokenIcon, duration=3.0, hpr=Vec3(360, 0, 0), startHpr=Vec3(0, 0, 0))) self.tokenIconIval.loop() icons.removeNode() def removeAdminToken(self): if self.tokenIcon != None and self.tokenIconIval != None: self.tokenIconIval.finish() self.tokenIcon.removeNode() self.tokenIconIval = None self.tokenIcon = None return def setChat(self, chatString): if not self.isThought(chatString): if not self.getGhost() or self.doId == base.localAvatar.doId: if 'ooo' in chatString.lower(): sfx = self.chatSoundDict['howl'] elif '!' in chatString.lower(): sfx = self.chatSoundDict['exclaim'] elif '?' in chatString.lower(): sfx = self.chatSoundDict['question'] elif len(chatString) <= 9: sfx = self.chatSoundDict['short'] elif 10 <= len(chatString) <= 19: sfx = self.chatSoundDict['medium'] elif len(chatString) >= 20: sfx = self.chatSoundDict['long'] sfx.play() Avatar.Avatar.setChat(self, chatString) def setName(self, nameString): Avatar.Avatar.setName(self, nameString, avatarType=self.avatarType) def setDNAStrand(self, dnaStrand, makeTag = 1): ToonDNA.ToonDNA.setDNAStrand(self, dnaStrand) self.deleteCurrentToon() self.generateToon(makeTag) def generateToon(self, makeTag = 1): self.generateLegs() self.generateTorso() self.generateHead() self.setToonColor() self.setClothes() self.setGloves() self.parentToonParts() self.rescaleToon() if makeTag: self.setupNameTag() Avatar.Avatar.initShadow(self) if self.cr.isShowingPlayerIds: self.showAvId() self.updateChatSoundDict() def attachTNT(self): self.pies.attachTNT() self.holdTNTAnim() def detachTNT(self): self.pies.detachTNT() self.animFSM.request(self.animFSM.getCurrentState().getName()) def holdTNTAnim(self): self.pose('toss', 22, partName='torso') def parentToonParts(self): self.attach('head', 'torso', 'def_head') self.attach('torso', 'legs', 'joint_hips') def unparentToonParts(self): self.getPart('head').reparentTo(self.getGeomNode()) self.getPart('torso').reparentTo(self.getGeomNode()) self.getPart('legs').reparentTo(self.getGeomNode()) def rescaleToon(self): animal = self.getAnimal() bodyScale = CIGlobals.toonBodyScales[animal] headScale = CIGlobals.toonHeadScales[animal][2] shoulderHeight = CIGlobals.legHeightDict[self.legs] * bodyScale + CIGlobals.torsoHeightDict[self.torso] * bodyScale height = shoulderHeight + CIGlobals.headHeightDict[self.head] * headScale bodyScale = CIGlobals.toonBodyScales[animal] self.setAvatarScale(bodyScale) self.setHeight(height) def setGloves(self): color = self.getGloveColor() gloves = self.find('**/hands') gloves.setColor(color) def setClothes(self): shirt, shirtcolor = self.getShirtStyle() short, shortcolor = self.getShortStyle() sleeve, sleevecolor = self.getSleeveStyle() torsot = self.findAllMatches('**/torso-top') torsob = self.findAllMatches('**/torso-bot') sleeves = self.findAllMatches('**/sleeves') torsot.setTexture(loader.loadTexture(shirt), 1) torsob.setTexture(loader.loadTexture(short), 1) sleeves.setTexture(loader.loadTexture(sleeve), 1) torsot.setColor(shirtcolor) sleeves.setColor(sleevecolor) torsob.setColor(shortcolor) def generateLegs(self): legtype = self.getLegs() self.loadModel('phase_3/models/char/tt_a_chr_' + legtype + '_shorts_legs_' + str(CIGlobals.getModelDetail(self.avatarType)) + '.bam', 'legs') self.loadAnims({'neutral': 'phase_3/models/char/tt_a_chr_' + legtype + '_shorts_legs_neutral.bam', 'run': 'phase_3/models/char/tt_a_chr_' + legtype + '_shorts_legs_run.bam', 'walk': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_walk.bam', 'pie': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_pie-throw.bam', 'fallb': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_slip-backward.bam', 'fallf': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_slip-forward.bam', 'lose': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_lose.bam', 'win': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_victory-dance.bam', 'squirt': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_water-gun.bam', 'zend': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_jump-zend.bam', 'tele': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_teleport.bam', 'book': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_book.bam', 'leap': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_leap_zhang.bam', 'jump': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_jump-zhang.bam', 'happy': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_jump.bam', 'shrug': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_shrug.bam', 'hdance': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_happy-dance.bam', 'wave': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_wave.bam', 'scemcee': 'phase_4/models/char/tt_a_chr_dgm_shorts_legs_scientistEmcee.bam', 'scwork': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_scientistWork.bam', 'scgame': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_scientistGame.bam', 'scjealous': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_scientistJealous.bam', 'swim': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_swim.bam', 'toss': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_toss.bam', 'cringe': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_cringe.bam', 'conked': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_conked.bam', 'catchneutral': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_gameneutral.bam', 'catchrun': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_gamerun.bam', 'hold-bottle': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_hold-bottle.bam', 'push-button': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_press-button.bam', 'happy-dance': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_happy-dance.bam', 'juggle': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_juggle.bam', 'shout': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_shout.bam', 'dneutral': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_sad-neutral.bam', 'dwalk': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_losewalk.bam', 'smooch': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_smooch.bam', 'conked': 'phase_3.5/models/char/tt_a_chr_' + legtype + '_shorts_legs_conked.bam', 'sound': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_shout.bam', 'sprinkle-dust': 'phase_5/models/char/tt_a_chr_' + legtype + '_shorts_legs_sprinkle-dust.bam', 'start-sit': 'phase_4/models/char/tt_a_chr_' + legtype + '_shorts_legs_intoSit.bam', 'sit': 'phase_4/models/char/char/tt_a_chr_' + legtype + '_shorts_legs_sit.bam'}, 'legs') self.findAllMatches('**/boots_long').stash() self.findAllMatches('**/boots_short').stash() self.findAllMatches('**/shoes').stash() def generateTorso(self): torsotype = self.getTorso() self.loadModel('phase_3/models/char/tt_a_chr_' + torsotype + '_torso_' + str(CIGlobals.getModelDetail(self.avatarType)) + '.bam', 'torso') self.loadAnims({'neutral': 'phase_3/models/char/tt_a_chr_' + torsotype + '_torso_neutral.bam', 'run': 'phase_3/models/char/tt_a_chr_' + torsotype + '_torso_run.bam', 'walk': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_walk.bam', 'pie': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_pie-throw.bam', 'fallb': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_slip-backward.bam', 'fallf': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_slip-forward.bam', 'lose': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_lose.bam', 'win': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_victory-dance.bam', 'squirt': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_water-gun.bam', 'zend': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_jump-zend.bam', 'tele': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_teleport.bam', 'book': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_book.bam', 'leap': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_leap_zhang.bam', 'jump': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_jump-zhang.bam', 'happy': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_jump.bam', 'shrug': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_shrug.bam', 'hdance': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_happy-dance.bam', 'wave': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_wave.bam', 'scemcee': 'phase_4/models/char/tt_a_chr_dgm_shorts_torso_scientistEmcee.bam', 'scwork': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_scientistWork.bam', 'scgame': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_scientistGame.bam', 'scjealous': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_scientistJealous.bam', 'swim': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_swim.bam', 'toss': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_toss.bam', 'cringe': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_cringe.bam', 'conked': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_conked.bam', 'catchneutral': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_gameneutral.bam', 'catchrun': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_gamerun.bam', 'hold-bottle': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_hold-bottle.bam', 'push-button': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_press-button.bam', 'happy-dance': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_happy-dance.bam', 'juggle': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_juggle.bam', 'shout': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_shout.bam', 'dneutral': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_sad-neutral.bam', 'dwalk': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_losewalk.bam', 'smooch': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_smooch.bam', 'conked': 'phase_3.5/models/char/tt_a_chr_' + torsotype + '_torso_conked.bam', 'sound': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_shout.bam', 'sprinkle-dust': 'phase_5/models/char/tt_a_chr_' + torsotype + '_torso_sprinkle-dust.bam', 'start-sit': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_intoSit.bam', 'sit': 'phase_4/models/char/tt_a_chr_' + torsotype + '_torso_sit.bam'}, 'torso') def generateHead(self, pat = 0): gender = self.getGender() head = self.getAnimal() headtype = self.getHead() ToonHead.generateHead(self, gender, head, headtype) def setToonColor(self): self.setHeadColor() self.setTorsoColor() self.setLegColor() def setLegColor(self): legcolor = self.getLegColor() self.findAllMatches('**/legs').setColor(legcolor) self.findAllMatches('**/feet').setColor(legcolor) def setTorsoColor(self): torsocolor = self.getTorsoColor() self.findAllMatches('**/arms').setColor(torsocolor) self.findAllMatches('**/neck').setColor(torsocolor) self.findAllMatches('**/hands').setColor(1, 1, 1, 1) def setForcedTorsoAnim(self, string): self.forcedTorsoAnim = string self.loop(string, partName='torso') def clearForcedTorsoAnim(self): self.forcedTorsoAnim = None self.animFSM.request(self.animFSM.getCurrentState().getName()) return def enterOff(self, ts = 0, callback = None, extraArgs = []): self.currentAnim = None return def exitOff(self): pass def enterWin(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'win' self.sfx = base.audio3d.loadSfx('phase_3.5/audio/sfx/ENC_Win.mp3') self.sfx.setLoop(True) base.audio3d.attachSoundToObject(self.sfx, self) base.playSfx(self.sfx) self.loop('win') def exitWin(self): self.stop() self.sfx.stop() del self.sfx self.playingAnim = 'neutral' def enterShrug(self, ts = 0, callback = None, extraArgs = []): self.play('shrug') def exitShrug(self): self.exitGeneral() def enterHDance(self, ts = 0, callback = None, extraArgs = []): self.play('hdance') def exitHDance(self): self.exitGeneral() def enterScientistWork(self, ts = 0, callback = None, extraArgs = []): self.loop('scwork') def exitScientistWork(self): self.exitGeneral() def enterScientistEmcee(self, ts = 0, callback = None, extraArgs = []): self.loop('scemcee') def exitScientistEmcee(self): self.exitGeneral() def enterScientistGame(self, ts = 0, callback = None, extraArgs = []): self.loop('scgame') def exitScientistGame(self): self.exitGeneral() def enterScientistJealous(self, ts = 0, callback = None, extraArgs = []): self.loop('scjealous') def exitScientistJealous(self): self.exitGeneral() def enterWave(self, ts = 0, callback = None, extraArgs = []): self.play('wave') def exitWave(self): self.exitGeneral() def enterLaugh(self, ts = 0, callback = None, extraArgs = []): self.setPlayRate(5.0, 'neutral') self.loop('neutral') def exitLaugh(self): self.setPlayRate(1.0, 'neutral') self.stop() def enterNeutral(self, ts = 0, callback = None, extraArgs = []): if self.backpack: if self.backpack.getCurrentGag(): if self.backpack.getCurrentGag().getState() != GagState.LOADED: self.loop('neutral', partName='legs') if self.animal == 'dog': self.loop('neutral', partName='head') return if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop('neutral', partName='legs') return else: self.loop('neutral') self.playingAnim = 'neutral' return def exitNeutral(self): self.exitGeneral() self.playingAnim = 'neutral' def exitGeneral(self): if self.backpack: if self.backpack.getCurrentGag(): if self.backpack.getCurrentGag().getState() != GagState.LOADED: self.stop(partName='legs') else: self.stop() else: self.stop() else: self.stop() def enterRun(self, ts = 0, callback = None, extraArgs = []): if self.backpack: if self.backpack.getCurrentGag(): if self.backpack.getCurrentGag().getState() != GagState.LOADED: self.loop('run', partName='legs') if self.animal == 'dog': self.loop('run', partName='head') return if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop('run', partName='legs') return else: self.loop('run') return def exitRun(self): self.exitGeneral() def enterWalk(self, ts = 0, callback = None, extraArgs = []): if self.backpack: if self.backpack.getCurrentGag(): if self.backpack.getCurrentGag().getState() != GagState.LOADED: self.loop('walk', partName='legs') if self.animal == 'dog': self.loop('walk', partName='head') return if self.forcedTorsoAnim != None: self.loop(self.forcedTorsoAnim, partName='torso') self.loop('walk', partName='legs') return else: self.loop('walk') return def exitWalk(self): self.exitGeneral() def enterWalkBack(self, ts = 0, callback = None, extraArgs = []): self.setPlayRate(-1.0, 'walk') self.enterWalk() def exitWalkBack(self): self.exitWalk() self.setPlayRate(1.0, 'walk') def enterOpenBook(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'book' self.book1 = Actor('phase_3.5/models/props/book-mod.bam', {'chan': 'phase_3.5/models/props/book-chan.bam'}) self.book1.reparentTo(self.getPart('torso').find('**/def_joint_right_hold')) self.track = ActorInterval(self, 'book', startFrame=CIGlobals.OpenBookFromFrame, endFrame=CIGlobals.OpenBookToFrame, name=self.uniqueName('enterOpenBook')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.__doCallback, [callback, extraArgs]) self.track.start(ts) self.book1.play('chan', fromFrame=CIGlobals.OpenBookFromFrame, toFrame=CIGlobals.OpenBookToFrame) def exitOpenBook(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None if self.book1: self.book1.cleanup() self.book1 = None self.playingAnim = 'neutral' return def enterReadBook(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'book' self.book2 = Actor('phase_3.5/models/props/book-mod.bam', {'chan': 'phase_3.5/models/props/book-chan.bam'}) self.book2.reparentTo(self.getPart('torso').find('**/def_joint_right_hold')) self.pingpong('book', fromFrame=CIGlobals.ReadBookFromFrame, toFrame=CIGlobals.ReadBookToFrame) self.book2.pingpong('chan', fromFrame=CIGlobals.ReadBookFromFrame, toFrame=CIGlobals.ReadBookToFrame) def exitReadBook(self): if self.book2: self.book2.cleanup() self.book2 = None self.playingAnim = 'neutral' return def enterCloseBook(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'book' self.book3 = Actor('phase_3.5/models/props/book-mod.bam', {'chan': 'phase_3.5/models/props/book-chan.bam'}) self.book3.reparentTo(self.getPart('torso').find('**/def_joint_right_hold')) self.track = ActorInterval(self, 'book', startFrame=CIGlobals.CloseBookFromFrame, endFrame=CIGlobals.CloseBookToFrame, name=self.uniqueName('enterCloseBook')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.__doCallback, [callback, extraArgs]) self.track.start(ts) self.book3.play('chan', fromFrame=CIGlobals.CloseBookFromFrame, toFrame=CIGlobals.CloseBookToFrame) def exitCloseBook(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None if self.book3: self.book3.cleanup() self.book3 = None self.playingAnim = 'neutral' return def enterTeleportOut(self, ts = 0, callback = None, extraArgs = []): self.notify.info(str(self.doId) + '-' + str(self.zoneId) + ': enterTeleportOut') self.playingAnim = 'tele' self.portal1 = Actor('phase_3.5/models/props/portal-mod.bam', {'chan': 'phase_3.5/models/props/portal-chan.bam'}) self.portal1.play('chan') self.portal1.reparentTo(self.getPart('legs').find('**/def_joint_right_hold')) self.play('tele') if hasattr(self, 'uniqueName'): name = self.uniqueName('enterTeleportOut') else: name = 'enterTeleportOut' self.track = Sequence(Wait(0.4), Func(self.teleportOutSfx), Wait(1.3), Func(self.throwPortal), Wait(3.4), name=name) self.track.delayDelete = DelayDelete.DelayDelete(self, name) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), self.teleportOutDone, [callback, extraArgs]) self.track.start(ts) def doPortalBins(self, portal): portal.setBin('shadow', 0) portal.setDepthWrite(0) portal.setDepthTest(0) def teleportOutDone(self, callback, requestStatus): self.notify.info(str(self.doId) + '-' + str(self.zoneId) + ': teleportOutDone') self.__doCallback(callback, requestStatus) self.exitTeleportOut() def teleportOutSfx(self): self.outSfx = base.audio3d.loadSfx('phase_3.5/audio/sfx/AV_teleport.mp3') base.audio3d.attachSoundToObject(self.outSfx, self.portal1) self.outSfx.play() def throwPortal(self): self.doPortalBins(self.portal1) self.portal1.reparentTo(self.getPart('legs').find('**/joint_nameTag')) self.portal1.setScale(CIGlobals.PortalScale) self.portal1.setY(6.5) self.portal1.setH(180) def exitTeleportOut(self): self.notify.info(str(self.doId) + '-' + str(self.zoneId) + ': exitTeleportOut') if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if self.portal1: self.portal1.cleanup() self.portal1 = None self.playingAnim = 'neutral' return def getTeleportInTrack(self, portal): self.doPortalBins(portal) holeTrack = Sequence() holeTrack.append(Func(portal.reparentTo, self)) pos = Point3(0, -2.4, 0) holeTrack.append(Func(portal.setPos, pos)) holeTrack.append(ActorInterval(portal, 'chan', startTime=3.4, endTime=3.1)) holeTrack.append(Wait(0.6)) holeTrack.append(ActorInterval(portal, 'chan', startTime=3.1, endTime=3.4)) def restorePortal(portal): portal.setPos(0, 0, 0) portal.detachNode() portal.clearBin() portal.clearDepthTest() portal.clearDepthWrite() holeTrack.append(Func(restorePortal, portal)) toonTrack = Sequence(Wait(0.3), Func(self.getGeomNode().show), Func(self.getNameTag().show), ActorInterval(self, 'happy', startTime=0.45)) if hasattr(self, 'uniqueName'): trackName = self.uniqueName('teleportIn') else: trackName = 'teleportIn' return Parallel(toonTrack, holeTrack, name=trackName) def enterTeleportIn(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'happy' self.portal2 = Actor('phase_3.5/models/props/portal-mod.bam', {'chan': 'phase_3.5/models/props/portal-chan.bam'}) self.show() self.getGeomNode().hide() self.getNameTag().hide() self.track = self.getTeleportInTrack(self.portal2) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getName(), self.teleportInDone, [callback, extraArgs]) self.track.delayDelete = DelayDelete.DelayDelete(self, self.track.getName()) self.track.start(ts) def teleportInDone(self, callback, extraArgs): self.__doCallback(callback, extraArgs) self.exitTeleportIn() def exitTeleportIn(self): if self.track != None: self.ignore(self.track.getName()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None if self.portal2: self.portal2.cleanup() self.portal2 = None if self.getGeomNode(): self.getGeomNode().show() if self.getNameTag(): self.getNameTag().show() self.playingAnim = 'neutral' return def enterFallFWD(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'fallf' self.play('fallf') Sequence(Wait(0.5), Func(self.fallSfx.play)).start() def exitFallFWD(self): self.exitGeneral() self.playingAnim = 'neutral' def enterFallBCK(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'fallb' self.play('fallb') Sequence(Wait(0.5), Func(self.fallSfx.play)).start() def exitFallBCK(self): self.playingAnim = 'neutral' self.exitGeneral() def enterHappyJump(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'happy' self.play('happy') def exitHappyJump(self): self.exitGeneral() self.playingAnim = 'neutral' def enterSwim(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'swim' self.loop('swim') self.getGeomNode().setP(-89.0) self.getGeomNode().setZ(4.0) nt = self.getNameTag() nt.setX(0) nt.setY(-2) nt.setZ(5.0) def exitSwim(self): self.exitGeneral() self.getGeomNode().setP(0.0) self.getGeomNode().setZ(0.0) nt = self.getNameTag() nt.setX(0) nt.setY(0) nt.setZ(self.getHeight() + 0.3) self.playingAnim = 'neutral' def enterDied(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'lose' self.isdying = True self.play('lose') self.track = Sequence(Wait(2.2), Func(self.dieSfx), Wait(2.8), self.getGeomNode().scaleInterval(2, Point3(0.01), startScale=self.getGeomNode().getScale()), Func(self.delToon), name=self.uniqueName('enterDied')) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.diedDone, [callback, extraArgs]) self.track.delayDelete = DelayDelete.DelayDelete(self, 'enterTeleportOut') self.track.start(ts) def diedDone(self, callback, extraArgs): self.__doCallback(callback, extraArgs) self.exitDied() def __doCallback(self, callback, extraArgs): if callback: if extraArgs: callback(*extraArgs) else: callback() def dieSfx(self): self.Losesfx = base.audio3d.loadSfx('phase_5/audio/sfx/ENC_Lose.mp3') base.audio3d.attachSoundToObject(self.Losesfx, self) self.Losesfx.play() def delToon(self): self.isdead = True def exitDied(self): if self.track != None: self.ignore(self.track.getDoneEvent()) self.track.finish() DelayDelete.cleanupDelayDeletes(self.track) self.track = None self.rescaleToon() self.playingAnim = 'neutral' return def enterJump(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'jump' self.loop('jump') def exitJump(self): self.exitGeneral() self.playingAnim = 'neutral' def enterLeap(self, ts = 0, callback = None, extraArgs = []): self.playingAnim = 'leap' self.loop('leap') def exitLeap(self): self.exitGeneral() self.playingAnim = 'neutral' def enterCringe(self, ts = 0, callback = None, extraArgs = []): self.play('cringe') def exitCringe(self): self.exitGeneral() def enterConked(self, ts = 0, callback = None, extraArgs = []): self.play('conked') def exitConked(self): self.exitGeneral()
class DistributedButterflyAI(DistributedNodeAI): notify = directNotify.newCategory('DistributedButterflyAI') def __init__(self, air, hood, wingType): DistributedNodeAI.__init__(self, air) self.hood = hood self.wingType = wingType self.state = 0 self.stateChangeTimestamp = 0.0 self.fromLoc = 0 self.toLoc = 0 self.fsm = ClassicFSM('DBFAI', [State('off', self.enterOff, self.exitOff), State('sit', self.enterSit, self.exitSit), State('fly', self.enterFly, self.exitFly)], 'off', 'off') self.fsm.enterInitialState() def enterOff(self): pass def exitOff(self): pass def enterSit(self, fromLoc, toLoc): taskMgr.doMethodLater(random.uniform(*ButterflyGlobals.SitTime), self.__flySomewhere, self.uniqueName('stopSittingTask')) def __flySomewhere(self, task): toLoc = ButterflyGlobals.Spots[self.hood].index(random.choice(ButterflyGlobals.Spots[self.hood])) fromLoc = self.toLoc self.b_setState(2, fromLoc, toLoc) return task.done def exitSit(self): taskMgr.remove(self.uniqueName('stopSittingTask')) def enterFly(self, fromLoc, toLoc): distance = (ButterflyGlobals.Spots[self.hood][toLoc] - ButterflyGlobals.Spots[self.hood][fromLoc]).length() time = distance / ButterflyGlobals.Speed taskMgr.doMethodLater(time, self.__land, self.uniqueName('landTask')) def __land(self, task): self.b_setState(1, self.toLoc, self.toLoc) return task.done def exitFly(self): taskMgr.remove(self.uniqueName('landTask')) def setState(self, state, fromLoc, toLoc): self.state = state self.fromLoc = fromLoc self.toLoc = toLoc self.fsm.request(ButterflyGlobals.StateIdx2State[state], [fromLoc, toLoc]) def b_setState(self, state, fromLoc, toLoc): self.setState(state, fromLoc, toLoc) self.d_setState(state, fromLoc, toLoc) def d_setState(self, state, fromLoc, toLoc): self.stateChangeTimestamp = globalClockDelta.getRealNetworkTime() self.sendUpdate('setState', [state, fromLoc, toLoc, self.stateChangeTimestamp]) def getState(self): return [self.state, self.fromLoc, self.toLoc, self.stateChangeTimestamp] def getWingType(self): return self.wingType def getHood(self): return self.hood def announceGenerate(self): DistributedNodeAI.announceGenerate(self) loc = ButterflyGlobals.Spots[self.hood].index(random.choice(ButterflyGlobals.Spots[self.hood])) self.b_setState(1, loc, loc) def delete(self): self.fsm.requestFinalState() self.hood = None self.state = None self.toLoc = None self.fromLoc = None self.stateChangeTimestamp = None self.wingType = None DistributedNodeAI.delete(self)
class AdminPage(StateData): notify = directNotify.newCategory('AdminPage') def __init__(self, book, parentFSM): self.book = book self.parentFSM = parentFSM StateData.__init__(self, 'adminPageDone') self.fsm = ClassicFSM('AdminPage', [State('off', self.enterOff, self.exitOff), State('basePage', self.enterBasePage, self.exitBasePage), State('kickSection', self.enterKickSection, self.exitKickSection), State('sysMsgSection', self.enterSysMsgSection, self.exitSysMsgSection)], 'off', 'off') self.fsm.enterInitialState() self.parentFSM.getStateNamed('adminPage').addChild(self.fsm) def enterOff(self): pass def exitOff(self): pass def enter(self): StateData.enter(self) self.fsm.request('basePage') def exit(self): self.fsm.requestFinalState() StateData.exit(self) def unload(self): del self.book del self.parentFSM del self.fsm StateData.unload(self) def enterSysMsgSection(self): self.book.createPageButtons(None, None) self.book.setTitle('System Message') geom = CIGlobals.getDefaultBtnGeom() self.infoLbl = OnscreenText(text='Inform all online players about something.', pos=(0, 0.45)) self.msgEntry = DirectEntry(initialText='System Message...', scale=0.055, width=15, numLines=4, command=self.sendSystemMessageCommand, focusInCommand=base.localAvatar.chatInput.disableKeyboardShortcuts, focusOutCommand=base.localAvatar.chatInput.enableKeyboardShortcuts, pos=(-0.4, 0, 0)) self.sendBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Send', pos=(0, 0, -0.35), text_pos=(0, -0.01), command=self.sendSystemMessageCommand) self.cancelBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Cancel', pos=(-0.45, 0.15, -0.55), text_pos=(0, -0.01), command=self.fsm.request, extraArgs=['basePage']) return def sendSystemMessageCommand(self, foo = None): msg = self.msgEntry.get() base.cr.myDistrict.sendUpdate('systemMessageCommand', [base.localAvatar.getAdminToken(), msg]) self.fsm.request('basePage') def exitSysMsgSection(self): self.infoLbl.destroy() del self.infoLbl self.msgEntry.destroy() del self.msgEntry self.sendBtn.destroy() del self.sendBtn self.cancelBtn.destroy() del self.cancelBtn self.book.clearTitle() self.book.deletePageButtons(False, False) def enterKickSection(self): self.book.createPageButtons(None, None) self.book.setTitle('Kick Player') geom = CIGlobals.getDefaultBtnGeom() self.infoLbl = OnscreenText(text='Type the ID of the player you want to boot out.', pos=(0, 0.45)) self.idEntry = DirectEntry(width=10, scale=0.12, pos=(-0.59, 0, 0.15), command=self.sendKickMessage, focusInCommand=base.localAvatar.chatInput.disableKeyboardShortcuts, focusOutCommand=base.localAvatar.chatInput.enableKeyboardShortcuts) self.kickBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Kick', pos=(0, 0, -0.15), text_pos=(0, -0.01), command=self.sendKickMessage) self.banBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Ban', pos=(0, 0, -0.25), text_pos=(0, -0.01), command=self.sendKickMessage, extraArgs=[None, 1]) self.cancelBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Cancel', pos=(-0.45, 0.15, -0.45), text_pos=(0, -0.01), command=self.fsm.request, extraArgs=['basePage']) return def sendKickMessage(self, foo = None, andBan = 0): if self.idEntry.get().isspace() or len(self.idEntry.get()) == 0: return print 'Sending out kick request for avatar id: ' + str(self.idEntry.get()) base.localAvatar.sendUpdate('requestEject', [int(self.idEntry.get()), andBan]) self.fsm.request('basePage') def exitKickSection(self): self.banBtn.destroy() del self.banBtn self.infoLbl.destroy() del self.infoLbl self.cancelBtn.destroy() del self.cancelBtn self.idEntry.destroy() del self.idEntry self.kickBtn.destroy() del self.kickBtn self.book.deletePageButtons(False, False) self.book.clearTitle() def enterBasePage(self): self.book.createPageButtons('releaseNotesPage', None) self.book.setTitle('Admin Stuff') geom = CIGlobals.getDefaultBtnGeom() self.suitSpawnerBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='', pos=(-0.45, 0.15, 0.5), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['suitSpawner']) self.killCogsBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Kill All Cogs', pos=(-0.45, 0.15, 0.4), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['killCogs']) self.makeTournamentBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Make Cog Tournament', pos=(-0.45, 0.15, 0.3), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['tournament']) self.makeInvasionBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Make Cog Invasion', pos=(-0.45, 0.15, 0.2), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['invasion']) self.makeCogBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Make Cog', pos=(-0.45, 0.15, 0.1), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['suit']) self.ghostBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='', pos=(0.45, 0.15, 0.5), text_pos=(0, -0.01), command=self.changeGhost) self.bgBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Toggle Background', pos=(0.45, 0.15, 0.4), text_pos=(0, -0.01), command=self.toggleBackground) self.idBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Toggle Player Ids', pos=(0.45, 0.15, 0.3), text_pos=(0, -0.01), command=self.togglePlayerIds) self.kickBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Kick Player', pos=(0.45, 0.15, 0.2), text_pos=(0, -0.01), command=self.openKickPage) self.systemMsgBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='System Message', pos=(0.45, 0.15, 0.1), text_pos=(0, -0.01), command=self.openSysMsgPage) if base.localAvatar.getGhost(): self.ghostBtn['text'] = 'Turn Ghost Off' else: self.ghostBtn['text'] = 'Turn Ghost On' base.cr.playGame.getPlace().maybeUpdateAdminPage() del geom return def togglePlayerIds(self): if base.cr.isShowingPlayerIds: base.cr.hidePlayerIds() else: base.cr.showPlayerIds() def toggleBackground(self): if render.isHidden(): render.show() else: render.hide() if self.book.book_img.isHidden(): self.book.book_img.show() else: self.book.book_img.hide() def changeGhost(self): if base.localAvatar.getGhost(): base.localAvatar.b_setGhost(0) self.ghostBtn['text'] = 'Turn Ghost On' else: base.localAvatar.b_setGhost(1) self.ghostBtn['text'] = 'Turn Ghost Off' def sendSuitCommand(self, commandName): if base.cr.playGame.suitManager: base.cr.playGame.suitManager.sendUpdate('suitAdminCommand', [base.localAvatar.getAdminToken(), commandName]) def openKickPage(self): self.fsm.request('kickSection') def openSysMsgPage(self): self.fsm.request('sysMsgSection') def exitBasePage(self): self.systemMsgBtn.destroy() del self.systemMsgBtn self.idBtn.destroy() del self.idBtn self.kickBtn.destroy() del self.kickBtn self.bgBtn.destroy() del self.bgBtn self.ghostBtn.destroy() del self.ghostBtn self.suitSpawnerBtn.destroy() del self.suitSpawnerBtn self.killCogsBtn.destroy() del self.killCogsBtn self.makeTournamentBtn.destroy() del self.makeTournamentBtn self.makeInvasionBtn.destroy() del self.makeInvasionBtn self.makeCogBtn.destroy() del self.makeCogBtn self.book.clearTitle() self.book.deletePageButtons(True, False)
class TownLoader(StateData): notify = directNotify.newCategory('TownLoader') def __init__(self, hood, parentFSMState, doneEvent): self.hood = hood self.parentFSMState = parentFSMState StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('TownLoader', [State('start', self.enterStart, self.exitStart, ['quietZone', 'street']), State('street', self.enterStreet, self.exitStreet, ['quietZone']), State('toonInterior', self.enterToonInterior, self.exitToonInterior, ['quietZone']), State('quietZone', self.enterQuietZone, self.exitQuietZone, ['street', 'toonInterior']), State('final', self.enterFinal, self.exitFinal, ['start'])], 'start', 'final') self.branchZone = None self.canonicalBranchZone = None self.placeDoneEvent = 'placeDone' self.linkTunnels = [] return def findAndMakeLinkTunnels(self, requestStatus): for tunnel in self.geom.findAllMatches('**/*linktunnel*'): dnaRootStr = tunnel.getName() zone = LinkTunnel.getZoneFromDNARootStr(dnaRootStr) zone = LinkTunnel.maybeFixZone(zone) tunnelClass = LinkTunnel.getRecommendedTunnelClassFromZone(zone) link = tunnelClass(tunnel, dnaRootStr) self.linkTunnels.append(link) def load(self, zoneId): StateData.load(self) self.zoneId = zoneId self.branchZone = ZoneUtil.getBranchZone(zoneId) self.canonicalBranchZone = ZoneUtil.getCanonicalBranchZone(zoneId) self.music = base.loadMusic(self.musicFile) self.interiorMusic = base.loadMusic(self.interiorMusicFile) def unload(self): self.parentFSMState.removeChild(self.fsm) del self.parentFSMState del self.fsm del self.streetClass self.landmarkBlocks.removeNode() del self.landmarkBlocks self.hood.dnaStore.resetSuitPoints() self.hood.dnaStore.resetBattleCells() del self.hood del self.nodeDict del self.zoneDict del self.fadeInDict del self.fadeOutDict del self.nodeList self.geom.removeNode() del self.geom del self.music del self.interiorMusic ModelPool.garbageCollect() TexturePool.garbageCollect() StateData.unload(self) def enter(self, requestStatus): StateData.enter(self) self.findAndMakeLinkTunnels(requestStatus) self.fsm.enterInitialState() self.setState(requestStatus['where'], requestStatus) def exit(self): self.fsm.requestFinalState() self.ignoreAll() ModelPool.garbageCollect() TexturePool.garbageCollect() StateData.exit(self) def setState(self, state, requestStatus): self.fsm.request(state, [requestStatus]) def enterStart(self): pass def exitStart(self): pass def enterStreet(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.streetDone) self.place = self.streetClass(self, self.fsm, self.placeDoneEvent) self.place.load() def exitStreet(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) return def streetDone(self): self.requestStatus = self.place.doneStatus status = self.place.doneStatus if status['loader'] == 'townLoader' and ZoneUtil.getBranchZone(status['zoneId']) == self.branchZone and status['shardId'] == None or status['how'] == 'doorOut': self.fsm.request('quietZone', [status]) else: self.doneStatus = status messenger.send(self.doneEvent) return def enterToonInterior(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.handleToonInteriorDone) self.place = ToonInterior.ToonInterior(self, self.fsm, self.placeDoneEvent) self.place.load() def exitToonInterior(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) return def enterThePlace(self, requestStatus): base.cr.playGame.setPlace(self.place) self.place.enter(requestStatus) def handleToonInteriorDone(self): status = self.place.doneStatus if status['loader'] == 'townLoader' and ZoneUtil.getBranchZone(status['zoneId']) == self.branchZone and status['shardId'] == None or status['how'] == 'doorOut': self.fsm.request('quietZone', [status]) else: self.doneStatus = status messenger.send(self.doneEvent) return def enterQuietZone(self, requestStatus): self.fsm.request(requestStatus['where'], [requestStatus], exitCurrent=0) self.quietZoneDoneEvent = uniqueName('quietZoneDone') self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone) self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent) self.quietZoneStateData.load() self.quietZoneStateData.enter(requestStatus) def exitQuietZone(self): self.ignore(self.quietZoneDoneEvent) del self.quietZoneDoneEvent self.quietZoneStateData.exit() self.quietZoneStateData.unload() self.quietZoneStateData = None return def handleQuietZoneDone(self): status = self.quietZoneStateData.getRequestStatus() self.exitQuietZone() self.enterThePlace(status) def enterFinal(self): pass def exitFinal(self): pass def createHood(self, dnaFile, loadStorage = 1): if loadStorage: loader.loadDNAFile(self.hood.dnaStore, 'phase_5/dna/storage_town.dna') loader.loadDNAFile(self.hood.dnaStore, self.townStorageDNAFile) node = loader.loadDNAFile(self.hood.dnaStore, dnaFile) if node.getNumParents() == 1: self.geom = NodePath(node.getParent(0)) self.geom.reparentTo(hidden) else: self.geom = hidden.attachNewNode(node) self.makeDictionaries(self.hood.dnaStore) self.reparentLandmarkBlockNodes() self.renameFloorPolys(self.nodeList) gsg = base.win.getGsg() if gsg: self.geom.prepareScene(gsg) self.geom.flattenLight() self.geom.setName('town_top_level') def reparentLandmarkBlockNodes(self): bucket = self.landmarkBlocks = hidden.attachNewNode('landmarkBlocks') npc = self.geom.findAllMatches('**/sb*:*_landmark_*_DNARoot') for i in xrange(npc.getNumPaths()): nodePath = npc.getPath(i) nodePath.wrtReparentTo(bucket) npc = self.geom.findAllMatches('**/sb*:*animated_building*_DNARoot') for i in xrange(npc.getNumPaths()): nodePath = npc.getPath(i) nodePath.wrtReparentTo(bucket) def makeDictionaries(self, dnaStore): self.nodeDict = {} self.zoneDict = {} self.zoneVisDict = {} self.nodeList = [] self.fadeInDict = {} self.fadeOutDict = {} a1 = Vec4(1, 1, 1, 1) a0 = Vec4(1, 1, 1, 0) numVisGroups = dnaStore.getNumDNAVisGroupsAI() for i in xrange(numVisGroups): groupFullName = dnaStore.getDNAVisGroupName(i) visGroup = dnaStore.getDNAVisGroupAI(i) groupName = base.cr.hoodMgr.extractGroupName(groupFullName) zoneId = int(groupName) zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId) groupNode = self.geom.find('**/' + groupFullName) if groupNode.isEmpty(): continue else: if ':' in groupName: groupName = '%s%s' % (zoneId, groupName[groupName.index(':'):]) else: groupName = '%s' % zoneId groupNode.setName(groupName) groupNode.flattenMedium() self.nodeDict[zoneId] = [] self.nodeList.append(groupNode) self.zoneDict[zoneId] = groupNode visibles = [] for i in xrange(visGroup.getNumVisibles()): visibles.append(int(visGroup.visibles[i])) visibles.append(ZoneUtil.getBranchZone(zoneId)) self.zoneVisDict[zoneId] = visibles fadeDuration = 0.5 self.fadeOutDict[groupNode] = Sequence(Func(groupNode.setTransparency, 1), LerpColorScaleInterval(groupNode, fadeDuration, a0, startColorScale=a1), Func(groupNode.clearColorScale), Func(groupNode.clearTransparency), Func(groupNode.stash), name='fadeZone-' + str(zoneId), autoPause=1) self.fadeInDict[groupNode] = Sequence(Func(groupNode.unstash), Func(groupNode.setTransparency, 1), LerpColorScaleInterval(groupNode, fadeDuration, a1, startColorScale=a0), Func(groupNode.clearColorScale), Func(groupNode.clearTransparency), name='fadeZone-' + str(zoneId), autoPause=1) for i in xrange(numVisGroups): groupFullName = dnaStore.getDNAVisGroupName(i) zoneId = int(base.cr.hoodMgr.extractGroupName(groupFullName)) zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId) for j in xrange(dnaStore.getNumVisiblesInDNAVisGroup(i)): visName = dnaStore.getVisibleName(i, j) groupName = base.cr.hoodMgr.extractGroupName(visName) nextZoneId = int(groupName) nextZoneId = ZoneUtil.getTrueZoneId(nextZoneId, self.zoneId) visNode = self.zoneDict[nextZoneId] self.nodeDict[zoneId].append(visNode) self.hood.dnaStore.resetPlaceNodes() self.hood.dnaStore.resetDNAGroups() self.hood.dnaStore.resetDNAVisGroups() self.hood.dnaStore.resetDNAVisGroupsAI() def renameFloorPolys(self, nodeList): for i in nodeList: collNodePaths = i.findAllMatches('**/+CollisionNode') numCollNodePaths = collNodePaths.getNumPaths() visGroupName = i.node().getName() for j in xrange(numCollNodePaths): collNodePath = collNodePaths.getPath(j) bitMask = collNodePath.node().getIntoCollideMask() if bitMask.getBit(1): collNodePath.node().setName(visGroupName)
class DistributedBoat(DistributedObject): notify = directNotify.newCategory('DistributedBoat') def __init__(self, cr): DistributedObject.__init__(self, cr) self.fsm = ClassicFSM('DistributedBoat', [State('off', self.enterOff, self.exitOff), State('eastToWest', self.enterEastToWest, self.exitEastToWest), State('westToEast', self.enterWestToEast, self.exitWestToEast)], 'off', 'off') self.boat = None self.eastPier = None self.eastPierPath = 'east_pier' self.westPier = None self.westPierPath = 'west_pier' self.pierUpP = 0.0 self.pierDownP = -45.0 self.fogHorn = 'phase_5/audio/sfx/SZ_DD_foghorn.mp3' self.shipBell = 'phase_6/audio/sfx/SZ_DD_shipbell.mp3' self.waterLap = 'phase_6/audio/sfx/SZ_DD_waterlap.mp3' self.dockCreak = 'phase_6/audio/sfx/SZ_DD_dockcreak.mp3' self.eastWest = 'phase_6/paths/dd-e-w.bam' self.westEast = 'phase_6/paths/dd-w-e.bam' self.boatPath = '*donalds_boat*' self.track = None self.state = None return def __handleOnBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPDonaldsBoat) base.playSfx(self.soundWaterLap, looping=1) def __handleOffBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPRender) self.soundWaterLap.stop() def __pollBoat(self, task): try: self.boat = self.cr.playGame.hood.loader.geom.find('**/' + self.boatPath) except: return task.cont self.generated() return task.done def generate(self): DistributedObject.generate(self) self.soundFogHorn = base.loadSfx(self.fogHorn) self.soundShipBell = base.loadSfx(self.shipBell) self.soundWaterLap = base.loadSfx(self.waterLap) self.soundDockCreak = base.loadSfx(self.dockCreak) self.boat = self.cr.playGame.hood.loader.geom.find('**/' + self.boatPath) self.generated() def generated(self): self.eastPier = self.cr.playGame.hood.loader.geom.find('**/' + self.eastPierPath) self.westPier = self.cr.playGame.hood.loader.geom.find('**/' + self.westPierPath) base.cr.parentMgr.registerParent(CIGlobals.SPDonaldsBoat, self.boat) self.accept('enterdonalds_boat_floor', self.__handleOnBoat) self.accept('exitdonalds_boat_floor', self.__handleOffBoat) self.d_requestCurrentStateAndTimestamp() self.fsm.enterInitialState() def disable(self): base.taskMgr.remove(self.uniqueName('__pollBoat')) base.cr.parentMgr.unregisterParent(CIGlobals.SPDonaldsBoat) self.ignore('enterdonalds_boat_floor') self.ignore('exitdonalds_boat_floor') self.fsm.requestFinalState() del self.fsm del self.soundFogHorn del self.soundShipBell del self.soundWaterLap del self.soundDockCreak self.fogHorn = None self.shipBell = None self.waterLap = None self.dockCreak = None self.boat = None self.track = None self.pierDownP = None self.pierUpP = None self.eastPier = None self.eastPierPath = None self.westPier = None self.westPierPath = None self.boatPath = None self.westEast = None self.eastWest = None DistributedObject.disable(self) return def currentStateAndTimestamp(self, state, timestamp): self.setState(state, timestamp) def d_requestCurrentStateAndTimestamp(self): self.sendUpdate('requestCurrentStateAndTimestamp', []) def setState(self, state, timestamp = None): if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) self.state = state if self.boat: self.fsm.request(state, [ts]) return def enterEastToWest(self, ts = 0): moPath = Mopath.Mopath() moPath.loadFile(self.eastWest) moIval = MopathInterval(moPath, self.boat) self.track = Parallel(SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.eastPier), moIval, LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierDownP, 0), startHpr=(90, self.pierUpP, 0)), Sequence(Wait(15.0), Parallel(LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierUpP, 0), startHpr=(-90, self.pierDownP, 0)), Sequence(Wait(2.0), SoundInterval(self.soundDockCreak, node=self.westPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitEastToWest(self): if self.track: self.track.finish() self.track = None return def enterWestToEast(self, ts = 0): moPath = Mopath.Mopath() moPath.loadFile(self.westEast) moIval = MopathInterval(moPath, self.boat) self.track = Parallel(SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.westPier), moIval, LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierDownP, 0), startHpr=(-90, self.pierUpP, 0)), Sequence(Wait(15.0), Parallel(LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierUpP, 0), startHpr=(90, self.pierDownP, 0)), Sequence(Wait(2.0), SoundInterval(self.soundDockCreak, node=self.eastPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitWestToEast(self): if self.track: self.track.finish() self.track = None return def enterOff(self): pass def exitOff(self): pass
class RemoteToonBattleAvatar(RemoteAvatar): notify = directNotify.newCategory("RemoteToonBattleAvatar") def __init__(self, mg, cr, avId, gunName="pistol"): RemoteAvatar.__init__(self, mg, cr, avId) self.track = None self.gunName = gunName self.fsm = ClassicFSM('RemoteToonBattleAvatar', [ State('off', self.enterOff, self.exitOff), State('shoot', self.enterShoot, self.exitShoot), State('die', self.enterDie, self.exitDie), State('dead', self.enterDead, self.exitDead) ], 'off', 'off') self.fsm.enterInitialState() self.soundGrunt = None self.retrieveAvatar() def setTeam(self, team): RemoteAvatar.setTeam(self, team) self.teamText.node().setText(GGG.TeamNameById[team][0]) self.teamText.node().setTextColor(GGG.TeamColorById[team]) def setGunName(self, gunName): self.gunName = gunName self.avatar.attachGun(gunName) if self.gunName == 'shotgun': if self.team: color = GGG.TeamColorById[self.team] self.avatar.gun.setColorScale(color) elif self.gunName == 'sniper': if self.team: color = GGG.TeamColorById[self.team] self.avatar.gun.setColorScale(color) def getGunName(self): return self.gunName def retrieveAvatar(self): RemoteAvatar.retrieveAvatar(self) if self.avatar: self.soundGrunt = base.loadSfx( 'phase_4/audio/sfx/target_impact_grunt1.ogg') def enterOff(self): pass def exitOff(self): pass def grunt(self): base.playSfx(self.soundGrunt, node=self.avatar) def enterDead(self): if self.avatar: self.avatar.stash() def exitDead(self): if self.avatar: self.avatar.unstash() self.avatar.clearColorScale() self.avatar.getGeomNode().clearColorScale() self.avatar.clearTransparency() self.avatar.getGeomNode().clearTransparency() self.avatar.getNameTag().clearColorScale() def enterDie(self, ts): if self.avatar: dieSound = base.audio3d.loadSfx( self.avatar.getToonAnimalNoise('exclaim')) base.audio3d.attachSoundToObject(dieSound, self.avatar) self.avatar.setTransparency(1) self.avatar.getGeomNode().setTransparency(1) SoundInterval(dieSound, node=self.avatar).start() self.track = Sequence( Parallel( LerpColorScaleInterval(self.avatar.getGeomNode(), colorScale=VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1), duration=0.5), LerpColorScaleInterval(self.avatar.getNameTag(), colorScale=VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1), duration=0.5), ActorInterval(self.avatar, 'fallb')), Func(self.fsm.request, 'dead')) self.track.start() del dieSound def exitDie(self): self.resetTrack() def resetTrack(self): if self.track: self.track.pause() self.track = None #self.avatar.stop() def run(self): if self.avatar: if self.track and self.track.isPlaying(): self.avatar.loop('run', partName='legs') else: self.avatar.loop('run') def strafe(self, playRate): if self.avatar: self.avatar.setPlayRate(playRate, 'strafe') if self.track and self.track.isPlaying(): self.avatar.loop('strafe', partName='legs') else: self.avatar.loop('strafe') def stand(self): if self.avatar: if self.track and self.track.isPlaying(): self.avatar.loop('neutral', partName='legs') else: self.avatar.loop('neutral') def jump(self): if self.avatar: if self.track and self.track.isPlaying(): self.avatar.loop('jump', partName='legs') else: self.avatar.loop('jump') def enterShoot(self, ts): if self.avatar: def createBullet(): if not self.avatar or not self.avatar.gun: return if self.gunName == "pistol": Bullet(self.mg, self.avatar.gun.find('**/joint_nozzle'), 0, self.gunName) elif self.gunName == "shotgun": b1 = Bullet(self.mg, self.avatar.gun.find('**/joint_nozzle'), 0, self.gunName) b2 = Bullet(self.mg, self.avatar.gun.find('**/joint_nozzle'), 0, self.gunName) elif self.gunName == "sniper": b1 = Bullet(self.mg, self.avatar.gun.find('**/joint_nozzle'), 0, self.gunName) b2 = Bullet(self.mg, self.avatar.gun.find('**/joint_nozzle'), 0, self.gunName) def changeToLegAnim(): if not self.avatar: return self.avatar.loop(self.avatar.getCurrentAnim(partName='legs')) if self.gunName == "pistol": gunSound = base.audio3d.loadSfx( "phase_4/audio/sfx/pistol_shoot.ogg") elif self.gunName == "shotgun": gunSound = base.audio3d.loadSfx( "phase_4/audio/sfx/shotgun_shoot.ogg") elif self.gunName == "sniper": gunSound = base.audio3d.loadSfx( "phase_4/audio/sfx/shotgun_shoot.ogg") base.audio3d.attachSoundToObject(gunSound, self.avatar) SoundInterval(gunSound, node=self.avatar).start() self.track = Sequence( Func(createBullet), ActorInterval(self.avatar, "squirt", partName='torso', startFrame=48, endFrame=58), ActorInterval(self.avatar, "squirt", partName='torso', startFrame=107, endFrame=126, playRate=3), Func(changeToLegAnim)) self.track.start() del gunSound self.mg.makeSmokeEffect( self.avatar.gun.find('**/joint_nozzle').getPos(render)) def exitShoot(self): self.resetTrack() def cleanup(self): if self.avatar: self.avatar.detachGun() self.soundGrunt = None if self.track: self.track.pause() del self.track RemoteAvatar.cleanup(self)
class DistributedWeatherCycle(DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedWeatherCycle') def __init__(self, cr): DistributedObject.__init__(self, cr) self.fsm = ClassicFSM(self.__class__.__name__, [ State('off', self.enterOff, self.exitOff, ['morning']), State('morning', self.enterMorning, self.exitMorning, ['afternoon']), State('afternoon', self.enterAfternoon, self.exitAfternoon, ['evening']), State('evening', self.enterEvening, self.exitEvening, ['midnight']), State('midnight', self.enterMidnight, self.exitMidnight, ['morning']) ], 'off', 'off') self.fsm.enterInitialState() self.__interval = None def setState(self, state): self.fsm.request(state) def getState(self): return self.fsm.getCurrentState()._State__name def setDuration(self, duration): self.duration = duration def getDuration(self): return self.duration def enterOff(self): pass def exitOff(self): pass def enterMorning(self): self.__interval = LerpColorScaleInterval( render, self.getDuration(), WeatherGlobals.cycleColors[0], startColorScale=render.getColorScale()) self.__interval.start() def exitMorning(self): if not self.__interval: return self.__interval.finish() self.__interval = None def enterAfternoon(self): self.__interval = LerpColorScaleInterval( render, self.getDuration(), WeatherGlobals.cycleColors[1], startColorScale=render.getColorScale()) self.__interval.start() def exitAfternoon(self): if not self.__interval: return self.__interval.finish() self.__interval = None def enterEvening(self): self.__interval = LerpColorScaleInterval( render, self.getDuration(), WeatherGlobals.cycleColors[2], startColorScale=render.getColorScale()) self.__interval.start() def exitEvening(self): if not self.__interval: return self.__interval.finish() self.__interval = None def enterMidnight(self): self.__interval = LerpColorScaleInterval( render, self.getDuration(), WeatherGlobals.cycleColors[3], startColorScale=render.getColorScale()) self.__interval.start() def exitMidnight(self): if not self.__interval: return self.__interval.finish() self.__interval = None
class DistributedBoat(DistributedObject): notify = directNotify.newCategory("DistributedBoat") def __init__(self, cr): DistributedObject.__init__(self, cr) self.fsm = ClassicFSM('DistributedBoat', [ State('off', self.enterOff, self.exitOff), State('eastToWest', self.enterEastToWest, self.exitEastToWest), State('westToEast', self.enterWestToEast, self.exitWestToEast) ], 'off', 'off') self.boat = None self.eastPier = None self.eastPierPath = 'east_pier' self.westPier = None self.westPierPath = 'west_pier' self.pierUpP = 0.0 self.pierDownP = -45.0 self.fogHorn = 'phase_5/audio/sfx/SZ_DD_foghorn.ogg' self.shipBell = 'phase_6/audio/sfx/SZ_DD_shipbell.ogg' self.waterLap = 'phase_6/audio/sfx/SZ_DD_waterlap.ogg' self.dockCreak = 'phase_6/audio/sfx/SZ_DD_dockcreak.ogg' self.eastWest = 'phase_6/paths/dd-e-w.bam' self.westEast = 'phase_6/paths/dd-w-e.bam' self.boatPath = '*donalds_boat*' self.track = None self.state = None def __handleOnBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPDonaldsBoat) base.playSfx(self.soundWaterLap, looping=1) def __handleOffBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPRender) self.soundWaterLap.stop() def __pollBoat(self, task): try: self.boat = self.cr.playGame.hood.loader.geom.find('**/' + self.boatPath) except: return task.cont self.generated() return task.done def generate(self): DistributedObject.generate(self) self.soundFogHorn = base.loadSfx(self.fogHorn) self.soundShipBell = base.loadSfx(self.shipBell) self.soundWaterLap = base.loadSfx(self.waterLap) self.soundDockCreak = base.loadSfx(self.dockCreak) #try: # self.boat = self.cr.playGame.hood.loader.geom.find('**/' + self.boatPath) #except: # base.taskMgr.add(self.__pollBoat, self.uniqueName('__pollBoat')) # return self.boat = self.cr.playGame.hood.loader.geom.find('**/' + self.boatPath) self.generated() def generated(self): self.eastPier = self.cr.playGame.hood.loader.geom.find( '**/' + self.eastPierPath) self.westPier = self.cr.playGame.hood.loader.geom.find( '**/' + self.westPierPath) base.cr.parentMgr.registerParent(CIGlobals.SPDonaldsBoat, self.boat) self.accept('enterdonalds_boat_floor', self.__handleOnBoat) self.accept('exitdonalds_boat_floor', self.__handleOffBoat) self.d_requestCurrentStateAndTimestamp() self.fsm.enterInitialState() def disable(self): base.taskMgr.remove(self.uniqueName('__pollBoat')) base.cr.parentMgr.unregisterParent(CIGlobals.SPDonaldsBoat) self.ignore('enterdonalds_boat_floor') self.ignore('exitdonalds_boat_floor') self.fsm.requestFinalState() del self.fsm del self.soundFogHorn del self.soundShipBell del self.soundWaterLap del self.soundDockCreak self.fogHorn = None self.shipBell = None self.waterLap = None self.dockCreak = None self.boat = None self.track = None self.pierDownP = None self.pierUpP = None self.eastPier = None self.eastPierPath = None self.westPier = None self.westPierPath = None self.boatPath = None self.westEast = None self.eastWest = None DistributedObject.disable(self) def currentStateAndTimestamp(self, state, timestamp): self.setState(state, timestamp) def d_requestCurrentStateAndTimestamp(self): self.sendUpdate('requestCurrentStateAndTimestamp', []) def setState(self, state, timestamp=None): if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) self.state = state if self.boat: self.fsm.request(state, [ts]) def enterEastToWest(self, ts=0): moPath = Mopath.Mopath() moPath.loadFile(self.eastWest) moIval = MopathInterval(moPath, self.boat) self.track = Parallel( SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.eastPier), moIval, LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierDownP, 0), startHpr=(90, self.pierUpP, 0)), Sequence( Wait(15.0), Parallel( LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierUpP, 0), startHpr=(-90, self.pierDownP, 0)), Sequence( Wait(2.0), SoundInterval(self.soundDockCreak, node=self.westPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitEastToWest(self): if self.track: self.track.finish() self.track = None def enterWestToEast(self, ts=0): moPath = Mopath.Mopath() moPath.loadFile(self.westEast) moIval = MopathInterval(moPath, self.boat) self.track = Parallel( SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.westPier), moIval, LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierDownP, 0), startHpr=(-90, self.pierUpP, 0)), Sequence( Wait(15.0), Parallel( LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierUpP, 0), startHpr=(90, self.pierDownP, 0)), Sequence( Wait(2.0), SoundInterval(self.soundDockCreak, node=self.eastPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitWestToEast(self): if self.track: self.track.finish() self.track = None def enterOff(self): pass def exitOff(self): pass
class OptionPage(StateData): def __init__(self, book, parentFSM): self.book = book self.parentFSM = parentFSM StateData.__init__(self, 'optionPageDone') self.fsm = ClassicFSM('OptionPage', [State('off', self.enterOff, self.exitOff), State('basePage', self.enterBasePage, self.exitBasePage), State('displayPage', self.enterDisplayPage, self.exitDisplayPage)], 'off', 'off') self.fsm.enterInitialState() self.parentFSM.getStateNamed('optionPage').addChild(self.fsm) def enterOff(self): pass def exitOff(self): pass def load(self): StateData.load(self) def unload(self): StateData.unload(self) def enter(self): StateData.enter(self) self.fsm.request('basePage') def exit(self): self.fsm.request('off') StateData.exit(self) def openDisplayPage(self): self.fsm.request('displayPage') def enterDisplayPage(self): self.book.createPageButtons(False, False) self.book.setTitle('Display Options') dialog_gui = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui.bam') width, height, fs, music, sfx, tex_detail, model_detail, aa, af = SettingsManager().getSettings('settings.json') self.width = width self.height = height self.windowType = [fs] self.buttons = [DirectRadioButton(text='Windowed', variable=self.windowType, value=[False], scale=0.1, pos=(-0.45, 0.15, 0.15)), DirectRadioButton(text='Fullscreen', variable=self.windowType, value=[True], scale=0.1, pos=(-0.45, -0.15, -0.15))] for button in self.buttons: button.setOthers(self.buttons) self.resoLbl = DirectLabel(text='%sx%s' % (width, height), scale=0.08, relief=None, pos=(0.25, 0, 0)) self.resSlider = DirectSlider(range=(0, 200), pageSize=50, command=self.setResoText, scale=0.3, orientation=DGG.VERTICAL, pos=(0.6, 0, 0)) self.okBtn = DirectButton(text='OK', geom=CIGlobals.getOkayBtnGeom(), relief=None, pos=(-0.5, -0.5, -0.5), text_scale=0.05, text_pos=(0, -0.11), command=self.applyDisplaySettings) self.cancelBtn = DirectButton(text='Cancel', geom=CIGlobals.getCancelBtnGeom(), relief=None, pos=(-0.3, -0.5, -0.5), text_scale=0.05, text_pos=(0, -0.11), command=self.cancelDisplaySettings) if self.resoLbl['text'] == '640x480': self.resSlider['value'] = 0 elif self.resoLbl['text'] == '800x600': self.resSlider['value'] = 50 elif self.resoLbl['text'] == '1024x768': self.resSlider['value'] = 100 elif self.resoLbl['text'] == '1280x1024': self.resSlider['value'] = 150 elif self.resoLbl['text'] == '1600x1200': self.resSlider['value'] = 200 return def exitDisplayPage(self): for button in self.buttons: button.destroy() del button self.resoLbl.destroy() del self.resoLbl self.resSlider.destroy() del self.resSlider self.okBtn.destroy() del self.okBtn self.cancelBtn.destroy() del self.cancelBtn del self.width del self.height del self.windowType del self.buttons self.book.clearTitle() def changeSetting(self, setting, value): if setting == 'music': if value: value = False elif not value: value = True base.enableMusic(value) self.music_btn['extraArgs'] = ['music', value] if value: valueTxt = 'On' else: valueTxt = 'Off' self.music_lbl['text'] = str(valueTxt).capitalize() elif setting == 'sfx': if value: value = False elif not value: value = True base.enableSoundEffects(value) self.sfx_btn['extraArgs'] = ['sfx', value] if value: valueTxt = 'On' else: valueTxt = 'Off' self.sfx_lbl['text'] = str(valueTxt).capitalize() elif setting == 'model-detail': if value == 'high': value = 'low' elif value == 'medium': value = 'high' elif value == 'low': value = 'medium' self.moddet_lbl['text'] = value.capitalize() self.moddet_btn['extraArgs'] = ['model-detail', value] elif setting == 'texture-detail': if value == 'normal': value = 'low' loadPrcFileData('', 'compressed-textures 1') elif value == 'low': value = 'normal' loadPrcFileData('', 'compressed-textures 0') self.texdet_lbl['text'] = value.capitalize() self.texdet_btn['extraArgs'] = ['texture-detail', value] elif setting == 'aa': if value == 'on': value = 'off' render.clear_antialias() elif value == 'off': value = 'on' render.set_antialias(AntialiasAttrib.MAuto) self.aa_lbl['text'] = value.capitalize() self.aa_btn['extraArgs'] = ['aa', value] elif setting == 'af': if value == 'on': value = 'off' elif value == 'off': value = 'on' self.af_lbl['text'] = value.capitalize() self.af_btn['extraArgs'] = ['af', value] SettingsManager().writeSettingToFile(setting, value, 'settings.json') def setResoText(self): if self.resSlider['value'] == 200: self.width = 1600 self.height = 1200 elif 150 <= self.resSlider['value'] <= 199: self.width = 1280 self.height = 1024 elif 100 <= self.resSlider['value'] <= 149: self.width = 1024 self.height = 768 elif 50 <= self.resSlider['value'] <= 99: self.width = 800 self.height = 600 elif self.resSlider['value'] == 0: self.width = 640 self.height = 480 self.resoLbl['text'] = str(self.width) + 'x' + str(self.height) def applyDisplaySettings(self): SettingsManager().writeSettingToFile('resolution', (self.width, self.height), 'settings.json', apply=1) SettingsManager().writeSettingToFile('fullscreen', self.windowType, 'settings.json', apply=1) self.fsm.request('basePage') def cancelDisplaySettings(self): self.fsm.request('basePage') def enterBasePage(self): self.book.createPageButtons(None, 'districtPage') self.book.setTitle('Options') width, height, fs, music, sfx, tex_detail, model_detail, aa, af = SettingsManager().getSettings('settings.json') if music: musicTxt = 'On' else: musicTxt = 'Off' if sfx: sfxTxt = 'On' else: sfxTxt = 'Off' if fs: fsTxt = 'On' else: fsTxt = 'Off' self.music_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Music', scale=1, text_scale=0.055, command=self.changeSetting, extraArgs=['music', music], pos=(-0.45, 0.55, 0.55), text_pos=(0, -0.01)) self.music_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, 0.55, 0.52), text_align=TextNode.ACenter) self.music_lbl['text'] = str(musicTxt).capitalize() self.sfx_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='SFX', scale=1, text_scale=0.055, command=self.changeSetting, extraArgs=['sfx', sfx], pos=(-0.45, 0.45, 0.45), text_pos=(0, -0.01)) self.sfx_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, 0.45, 0.42), text_align=TextNode.ACenter) self.sfx_lbl['text'] = str(sfxTxt).capitalize() self.moddet_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Model Detail', scale=1, text_scale=0.055, command=self.changeSetting, extraArgs=['model-detail', model_detail], pos=(-0.45, 0.35, 0.35), text_pos=(0, -0.01)) self.moddet_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, 0.35, 0.32), text_align=TextNode.ACenter) self.moddet_lbl['text'] = model_detail.capitalize() self.moddet_btn.bind(DGG.ENTER, self.createMustRestartGui) self.moddet_btn.bind(DGG.EXIT, self.removeMustRestartGui) self.texdet_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Texture Detail', scale=1, text_scale=0.0535, command=self.changeSetting, extraArgs=['texture-detail', tex_detail], pos=(-0.45, 0.25, 0.25), text_pos=(0, -0.01)) self.texdet_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, 0.25, 0.22), text_align=TextNode.ACenter) self.texdet_lbl['text'] = tex_detail.capitalize() self.texdet_btn.bind(DGG.ENTER, self.createMustRestartGui) self.texdet_btn.bind(DGG.EXIT, self.removeMustRestartGui) self.display_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Display', command=self.openDisplayPage, scale=1, text_scale=0.0535, pos=(-0.45, -0.25, 0.02), text_pos=(0, -0.01)) self.display_lbl = DirectLabel(relief=None, scale=0.06, pos=(0.45, -0.25, 0.02), text_align=TextNode.ACenter) self.display_lbl['text'] = 'Fullscreen: %s\nResolution: %s' % (str(fsTxt).capitalize(), (width, height)) self.aa_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Anti-Aliasing', command=self.changeSetting, extraArgs=['aa', aa], scale=1, text_scale=0.0535, pos=(-0.45, -0.35, -0.18), text_pos=(0, -0.01)) self.aa_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, -0.35, -0.21), text_align=TextNode.ACenter) self.aa_lbl['text'] = aa.capitalize() self.af_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Anisotropic Filtering', command=self.changeSetting, extraArgs=['af', af], scale=1, text_scale=0.0435, pos=(-0.45, -0.35, -0.28), text_pos=(0, -0.01)) self.af_lbl = DirectLabel(relief=None, scale=0.09, pos=(0.45, -0.35, -0.31), text_align=TextNode.ACenter) self.af_lbl['text'] = af.capitalize() self.af_btn.bind(DGG.ENTER, self.createMustRestartGui) self.af_btn.bind(DGG.EXIT, self.removeMustRestartGui) self.exit_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, text='Exit Toontown', scale=1.2, text_scale=0.0535, command=self.book.finished, extraArgs=['exit'], pos=(-0.45, -0.65, -0.6), text_pos=(0, -0.01)) return def createMustRestartGui(self, foo): self.mustRestartLbl = DirectLabel(text='Changing this setting requires a game restart.', text_fg=(0.9, 0, 0, 1), text_shadow=(0, 0, 0, 1), text_scale=0.06, text_align=TextNode.ACenter, pos=(0, 0, -0.435), relief=None) return def removeMustRestartGui(self, foo): if hasattr(self, 'mustRestartLbl'): self.mustRestartLbl.destroy() del self.mustRestartLbl def exitBasePage(self): self.music_btn.destroy() del self.music_btn self.sfx_btn.destroy() del self.sfx_btn self.moddet_btn.destroy() del self.moddet_btn self.texdet_btn.destroy() del self.texdet_btn self.display_btn.destroy() del self.display_btn self.aa_btn.destroy() del self.aa_btn self.exit_btn.destroy() del self.exit_btn self.music_lbl.destroy() del self.music_lbl self.sfx_lbl.destroy() del self.sfx_lbl self.moddet_lbl.destroy() del self.moddet_lbl self.texdet_lbl.destroy() del self.texdet_lbl self.display_lbl.destroy() del self.display_lbl self.aa_lbl.destroy() del self.aa_lbl self.af_btn.destroy() del self.af_btn self.af_lbl.destroy() del self.af_lbl self.book.deletePageButtons(False, True) self.book.clearTitle()
class NamePage(StateData): notify = directNotify.newCategory('NamePage') def __init__(self, book, parentFSM): self.book = book self.parentFSM = parentFSM StateData.__init__(self, 'namePageDone') self.fsm = ClassicFSM('NamePage', [ State('off', self.enterOff, self.exitOff), State('basePage', self.enterBasePage, self.exitBasePage) ], 'off', 'off') self.fsm.enterInitialState() self.parentFSM.getStateNamed('namePage').addChild(self.fsm) self.nameServ = base.cr.nameServicesManager self.baseRequestIndex = 0 self.requestsPerCluster = 5 self.requestsContainer = {} self.loadingLabel = None self.selectedName = None self.nameButtons = [] self.avId2NameData = {} geom = CIGlobals.getDefaultBtnGeom() self.acceptBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=0.5, text='Accept', pos=(0.5, posY, 0), text_pos=(0, -0.01), command=self.acceptName) self.acceptBtn.hide() self.declineBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=0.5, text='Decline', pos=(0.75, posY, 0), text_pos=(0, -0.01), command=self.declineName) self.declineBtn.hide() self.avIdLbl = OnscreenText(text='', scale=0.08, pos=(0.3, 0, 0.5), align=TextNode.ACenter) self.avIdLbl.hide() self.accIdLbl = OnscreenText(text='', scale=0.08, pos=(0.3, 0, 0.3), align=TextNode.ACenter) self.accIdLbl.hide() return def handleRequests(self): gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam') self.nameList = DirectScrolledList( relief=None, pos=(-0.54, 0, 0.08), incButton_image=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), incButton_relief=None, incButton_scale=(arrowButtonScale, arrowButtonScale, -arrowButtonScale), incButton_pos=(buttonXstart, 0, itemFrameZorigin - 0.999), incButton_image3_color=Vec4(1, 1, 1, 0.2), incButton_command=self.__moveItems, incButton_extraArgs=[1], decButton_image=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), decButton_relief=None, decButton_scale=(arrowButtonScale, arrowButtonScale, arrowButtonScale), decButton_pos=(buttonXstart, 0, itemFrameZorigin + 0.125), decButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_command=self.__moveItems, decButton_extraArgs=[0], itemFrame_pos=(itemFrameXorigin, 0, itemFrameZorigin), itemFrame_scale=1.0, itemFrame_relief=DGG.SUNKEN, itemFrame_frameSize=(listXorigin, listXorigin + listFrameSizeX, listZorigin, listZorigin + listFrameSizeZ), itemFrame_frameColor=(0.85, 0.95, 1, 1), itemFrame_borderWidth=(0.01, 0.01), numItemsVisible=5, forceHeight=0.075, items=self.nameButtons) self.__buildItems() return def __moveItems(self, direction): if direction == 0: self.baseRequestIndex += 1 else: if direction == 1: self.baseRequestIndex -= 1 self.clearItems() self.__buildItems() def clearItems(self): for btn in self.nameButtons: btn.destroy() self.nameButtons = [] self.nameList.removeAndDestroyAllItems() def __buildItems(self): for i in xrange(self.requestsPerCluster): request = self.nameServ.getNameRequests()[self.baseRequestIndex + i] date = request['date'] date = date.replace(' ', '-') data = NameData(request['name'], date, request['avId'], request['accId']) self.avId2NameData[data.avId] = data btn = DirectButton(relief=None, text=data.name, text_scale=0.07, text_align=TextNode.ALeft, text1_bg=textDownColor, text2_bg=textRolloverColor, text3_fg=textDisabledColor, textMayChange=0, command=self.__handleNameButton, extraArgs=[data], text_pos=(0, 0, 0.0)) data.btn = btn self.nameButtons.append(btn) self.loadingLabel.hide() return def __handleNameButton(self, data): self.selectedName = data data.btn['state'] = DGG.DISABLED self.avIdLbl.setText('Avatar ID:\n' + str(data.avId)) self.avIdLbl.show() self.accIdLbl.setText('Account ID:\n' + str(data.accId)) self.accIdLbl.show() self.acceptBtn.show() self.declineBtn.show() def acceptName(self): pass def load(self): StateData.load(self) self.loadingLabel = OnscreenText(text='Loading...', font=CIGlobals.getToonFont(), pos=(0, 0.1, 0), scale=0.08, parent=aspect2d) def unload(self): StateData.unload(self) self.loadingLabel.destroy() self.loadingLabel = None for request in self.requestsContainer.values(): for element in request: element.destroy() self.requestsContainer = {} return def enter(self): StateData.enter(self) self.fsm.request('basePage') base.acceptOnce(self.nameServ.getRequestCompleteName(), self.handleRequests) self.nameServ.d_requestNameData() def exit(self): self.fsm.requestFinalState() StateData.exit(self) def enterBasePage(self): self.book.createPageButtons('adminPage', None) self.book.setTitle('Name Approval') return def exitBasePage(self): self.book.deletePageButtons(True, False) self.book.clearTitle() def enterOff(self): pass def exitOff(self): pass
class ToonHood(Hood.Hood): def __init__(self, parentFSM, doneEvent, dnaStore, hoodId): Hood.Hood.__init__(self, parentFSM, doneEvent, dnaStore, hoodId) self.safeZoneLoader = None self.townLoader = None self.fsm = ClassicFSM('Hood', [ State('off', self.enterOff, self.exitOff), State('safeZoneLoader', self.enterSafeZoneLoader, self.exitSafeZoneLoader, ['quietZone', 'townLoader']), State('townLoader', self.enterTownLoader, self.exitTownLoader, ['quietZone', 'safeZoneLoader']), State('quietZone', self.enterQuietZone, self.exitQuietZone, ['safeZoneLoader', 'townLoader']) ], 'off', 'off') self.fsm.enterInitialState() return def loadLoader(self, requestStatus): loader = requestStatus['loader'] if loader == 'safeZoneLoader': if self.safeZoneLoader: self.loader = self.safeZoneLoader( self, self.fsm.getStateNamed('safeZoneLoader'), self.loaderDoneEvent) self.loader.load() else: self.notify.error( 'ToonHood.ToonHood.safeZoneLoader cannot be None!' % loader) else: if loader == 'townLoader': if self.townLoader: self.loader = self.townLoader( self, self.fsm.getStateNamed('townLoader'), self.loaderDoneEvent) self.loader.load(requestStatus['zoneId']) else: self.notify.error('Unknown loader %s!' % loader) def enterTownLoader(self, requestStatus): self.acceptOnce(self.loaderDoneEvent, self.handleTownLoaderDone) self.loader.enter(requestStatus) self.spawnTitleText(requestStatus['zoneId']) def exitTownLoader(self): taskMgr.remove('titleText') self.hideTitleText() self.ignore(self.loaderDoneEvent) self.loader.exit() self.loader.unload() del self.loader def handleTownLoaderDone(self): doneStatus = self.loader.getDoneStatus() if self.isSameHood(doneStatus): self.fsm.request('quietZone', [doneStatus]) else: self.doneStatus = doneStatus messenger.send(self.doneEvent) def load(self): Hood.Hood.load(self) self.whiteFogColor = Vec4(0.8, 0.8, 0.8, 1) self.underwaterFogColor = Vec4(0.0, 0.0, 0.6, 1.0) def unload(self): del self.safeZoneLoader Hood.Hood.unload(self) def enter(self, requestStatus): self.loadLoader(requestStatus) Hood.Hood.enter(self, requestStatus) def exit(self): Hood.Hood.exit(self) def setUnderwaterFog(self): if base.wantFog: self.fog.setColor(self.underwaterColor) self.fog.setLinearRange(0.1, 100.0) render.setFog(self.fog) self.sky.setFog(self.fog) def setWhiteFog(self): if base.wantFog: self.fog.setColor(self.whiteFogColor) self.fog.setLinearRange(0.0, 400.0) render.clearFog() render.setFog(self.fog) self.sky.clearFog() self.sky.setFog(self.fog) def setNoFog(self): if base.wantFog: render.clearFog() self.sky.clearFog()
class DistributedRaceGame(DistributedMinigame.DistributedMinigame): def __init__(self, cr): try: self.DistributedRaceGame_initialized return except: self.DistributedRaceGame_initialized = 1 DistributedMinigame.DistributedMinigame.__init__(self, cr) self.movement = RaceGameMovement.RaceGameMovement(base.localAvatar) self.skyUtil = SkyUtil() self.raceFSM = ClassicFSM('DistributedRaceGame', [ State('race', self.enterRace, self.exitRace), State('raceTransition', self.enterRaceTransition, self.exitRaceTransition), State('off', self.enterRaceOff, self.exitRaceOff) ], 'off', 'off') self.raceFSM.enterInitialState() self.cr = cr self.track = None self.sky = None self.countSfx = base.loadSfx("phase_5/audio/sfx/firehydrant_popup.ogg") self.goSfx = base.loadSfx("phase_4/audio/sfx/AA_sound_whistle.ogg") self.game = CIGlobals.RaceGame self.trackPath = "phase_4/models/minigames/sprint_track.egg" self.skyPath = "phase_3.5/models/props/TT_sky.bam" self.lanePos = [(-22.00, -205.00, 0.00), (-11.66, -205.00, 0.00), (0.00, -205.00, 0.00), (-33.66, -205.00, 0.00)] self.initialCamPos = { "pos": (41.10, -145.00, 25.88), "hpr": (135.00, 345.96, 0.0) } self.raceCamPos = (-24.52, -37.22, 25.00) self.lane = 0 return def load(self): self.deleteWorld() self.track = loader.loadModel(self.trackPath) self.track.reparentTo(render) self.sky = loader.loadModel(self.skyPath) self.sky.reparentTo(self.track) self.skyUtil.startSky(self.sky) self.setMinigameMusic("phase_4/audio/bgm/MG_toontag.ogg") self.setDescription("Tap the left and right arrow keys repeatedly, in turns, as fast as " + \ "you can to win the race! Every time your power bar hits the top, the boost bar starts" + \ " to fill. When the boost bar is full, press CTRL to boost for a few seconds.") self.setWinnerPrize(100) self.setLoserPrize(5) self.d_requestToonLane() camera.reparentTo(render) camera.setPos(self.initialCamPos["pos"]) camera.setHpr(self.initialCamPos["hpr"]) DistributedMinigame.DistributedMinigame.load(self) def enterPlay(self): DistributedMinigame.DistributedMinigame.enterPlay(self) self.raceFSM.request('raceTransition') def exitPlay(self): DistributedMinigame.DistributedMinigame.exitPlay(self) self.raceFSM.request('off') def enterRace(self): self.startMovement() def exitRace(self): self.stopMovement() def enterRaceOff(self): pass def exitRaceOff(self): pass def enterRaceTransition(self): self.raceTrans = Sequence(Wait(0.5), Func(self.moveCameraToToon), Wait(4.5), Func(self.moveCameraToTop), Wait(4.5), Func(self.startCountdown)) self.raceTrans.start() def exitRaceTransition(self): self.raceTrans.pause() del self.raceTrans def startMovement(self): self.movement.createGui() self.movement.fsm.request('run') def enterGameOver(self, winner=0, winnerDoId=0, allPrize=0): self.raceFSM.request('off') DistributedMinigame.DistributedMinigame.enterGameOver( self, winner, winnerDoId, allPrize) def stopMovement(self): self.movement.cleanup() self.movement.deleteGui() def startCountdown(self): """ Start the countdown to the start of the race. """ self.countdownLbl = DirectLabel(text="", text_scale=0.3, text_font=CIGlobals.getMickeyFont(), text_fg=(1, 1, 0, 1), pos=(0, 0, 0.5)) Sequence(Func(self.setCountdownText, "3"), Wait(1.0), Func(self.setCountdownText, "2"), Wait(1.0), Func(self.setCountdownText, "1"), Wait(1.0), Func(self.setCountdownText, "GO!"), Wait(1.5), Func(self.deleteCountdownLabel)).start() def setCountdownText(self, number): self.countdownLbl['text'] = number if number == "GO!": self.countdownLbl['text_fg'] = (0, 1, 0, 1) self.goSfx.play() self.raceFSM.request('race') else: self.countSfx.play() def deleteCountdownLabel(self): self.countdownLbl.destroy() del self.countdownLbl def moveCameraToToon(self): camPInt = LerpPosInterval(camera, duration=3.0, pos=self.localAv.getPos(render) + (0, 15, 3), startPos=(camera.getPos(render)), blendType="easeInOut") camQInt = camera.quatInterval(3.0, hpr=Vec3(180, 0, 0), blendType="easeInOut") camPInt.start() camQInt.start() def moveCameraToTop(self): camera.setPos(camera.getPos(self.localAv)) camera.reparentTo(self.localAv) oldPos = camera.getPos() camera.setPos(self.raceCamPos) oldHpr = camera.getHpr() camera.lookAt(self.localAv.getPart('head')) newHpr = camera.getHpr() camera.setHpr(oldHpr) camera.setPos(oldPos) camPInt = LerpPosInterval(camera, duration=3.0, pos=self.raceCamPos, startPos=oldPos, blendType="easeInOut") camQInt = camera.quatInterval(3.0, hpr=newHpr, blendType="easeInOut") camPInt.start() camQInt.start() def deleteWorld(self): if self.track: self.track.removeNode() self.track = None if self.sky: self.skyUtil.stopSky() self.sky.removeNode() self.sky = None def setToonLane(self, lane): self.lane = lane base.localAvatar.setPos(self.lanePos[lane]) base.localAvatar.setHpr(0, 0, 0) def getToonLane(self): return self.lane def d_requestToonLane(self): self.sendUpdate('requestToonLane', []) def announceGenerate(self): DistributedMinigame.DistributedMinigame.announceGenerate(self) self.load() def disable(self): DistributedMinigame.DistributedMinigame.disable(self) self.deleteWorld() self.raceFSM.requestFinalState() del self.raceFSM self.countSfx = None self.goSfx = None
class Street(Place): notify = directNotify.newCategory('Street') def __init__(self, loader, parentFSM, doneEvent): self.parentFSM = parentFSM Place.__init__(self, loader, doneEvent) self.fsm = ClassicFSM('Street', [State('start', self.enterStart, self.exitStart, ['walk', 'doorOut', 'teleportIn', 'tunnelOut']), State('walk', self.enterWalk, self.exitWalk, ['stop', 'tunnelIn', 'shtickerBook', 'teleportOut']), State('shtickerBook', self.enterShtickerBook, self.exitShtickerBook, ['teleportOut', 'walk']), State('teleportOut', self.enterTeleportOut, self.exitTeleportOut, ['teleportIn', 'stop']), State('tunnelOut', self.enterTunnelOut, self.exitTunnelOut, ['walk']), State('tunnelIn', self.enterTunnelIn, self.exitTunnelIn, ['stop']), State('stop', self.enterStop, self.exitStop, ['walk', 'died', 'teleportOut', 'doorIn']), State('doorIn', self.enterDoorIn, self.exitDoorIn, ['stop']), State('doorOut', self.enterDoorOut, self.exitDoorOut, ['walk']), State('teleportIn', self.enterTeleportIn, self.exitTeleportIn, ['walk', 'stop']), State('final', self.enterFinal, self.exitFinal, ['final'])], 'start', 'final') def enter(self, requestStatus, visibilityFlag = 1): Place.enter(self) self.fsm.enterInitialState() base.playMusic(self.loader.music, volume=0.8, looping=1) self.loader.geom.reparentTo(render) if visibilityFlag: self.visibilityOn() self.loader.hood.startSky() self.enterZone(requestStatus['zoneId']) self.fsm.request(requestStatus['how'], [requestStatus]) def exit(self, vis = 1): if vis: self.visibilityOff() self.loader.geom.reparentTo(hidden) self.loader.hood.stopSky() self.loader.music.stop() Place.exit(self) def load(self): Place.load(self) self.parentFSM.getStateNamed('street').addChild(self.fsm) def unload(self): self.parentFSM.getStateNamed('street').removeChild(self.fsm) del self.fsm del self.parentFSM self.enterZone(None) self.ignoreAll() Place.unload(self) return def hideAllVisibles(self): for i in self.loader.nodeList: i.stash() def showAllVisibles(self): for i in self.loader.nodeList: i.unstash() def visibilityOn(self): self.hideAllVisibles() self.accept('on-floor', self.enterZone) def visibilityOff(self): self.ignore('on-floor') self.showAllVisibles() def enterZone(self, newZone): if isinstance(newZone, CollisionEntry): try: newZoneId = int(newZone.getIntoNode().getName()) except: self.notify.warning('Invalid floor collision node in street: %s' % newZone.getIntoNode().getName()) return else: newZoneId = newZone self.doEnterZone(newZoneId) def doEnterZone(self, newZoneId): visualizeZones = 0 if self.zoneId != None: for i in self.loader.nodeDict[self.zoneId]: if newZoneId: if i not in self.loader.nodeDict[newZoneId]: self.loader.fadeOutDict[i].start() else: i.stash() if newZoneId != None: for i in self.loader.nodeDict[newZoneId]: if self.zoneId: if i not in self.loader.nodeDict[self.zoneId]: self.loader.fadeInDict[i].start() else: if self.loader.fadeOutDict[i].isPlaying(): self.loader.fadeOutDict[i].finish() if self.loader.fadeInDict[i].isPlaying(): self.loader.fadeInDict[i].finish() i.unstash() if newZoneId != self.zoneId: if visualizeZones: if self.zoneId != None: self.loader.zoneDict[self.zoneId].clearColor() if newZoneId != None: self.loader.zoneDict[newZoneId].setColor(0, 0, 1, 1, 100) if newZoneId is not None: loader = base.cr.playGame.getPlace().loader if newZoneId in loader.zoneVisDict: base.cr.sendSetZoneMsg(newZoneId, loader.zoneVisDict[newZoneId]) else: visList = [newZoneId] + loader.zoneVisDict.values()[0] base.cr.sendSetZoneMsg(newZoneId, visList) self.zoneId = newZoneId geom = base.cr.playGame.getPlace().loader.geom return
class ToonHead(Actor.Actor): notify = DirectNotifyGlobal.directNotify.newCategory('ToonHead') EyesOpen = loader.loadTexture('phase_3/maps/eyes.jpg', 'phase_3/maps/eyes_a.rgb') EyesOpen.setMinfilter(Texture.FTLinear) EyesOpen.setMagfilter(Texture.FTLinear) EyesClosed = loader.loadTexture('phase_3/maps/eyesClosed.jpg', 'phase_3/maps/eyesClosed_a.rgb') EyesClosed.setMinfilter(Texture.FTLinear) EyesClosed.setMagfilter(Texture.FTLinear) EyesSadOpen = loader.loadTexture('phase_3/maps/eyesSad.jpg', 'phase_3/maps/eyesSad_a.rgb') EyesSadOpen.setMinfilter(Texture.FTLinear) EyesSadOpen.setMagfilter(Texture.FTLinear) EyesSadClosed = loader.loadTexture('phase_3/maps/eyesSadClosed.jpg', 'phase_3/maps/eyesSadClosed_a.rgb') EyesSadClosed.setMinfilter(Texture.FTLinear) EyesSadClosed.setMagfilter(Texture.FTLinear) EyesAngryOpen = loader.loadTexture('phase_3/maps/eyesAngry.jpg', 'phase_3/maps/eyesAngry_a.rgb') EyesAngryOpen.setMinfilter(Texture.FTLinear) EyesAngryOpen.setMagfilter(Texture.FTLinear) EyesAngryClosed = loader.loadTexture('phase_3/maps/eyesAngryClosed.jpg', 'phase_3/maps/eyesAngryClosed_a.rgb') EyesAngryClosed.setMinfilter(Texture.FTLinear) EyesAngryClosed.setMagfilter(Texture.FTLinear) EyesSurprised = loader.loadTexture('phase_3/maps/eyesSurprised.jpg', 'phase_3/maps/eyesSurprised_a.rgb') EyesSurprised.setMinfilter(Texture.FTLinear) EyesSurprised.setMagfilter(Texture.FTLinear) Muzzle = loader.loadTexture('phase_3/maps/muzzleShrtGeneric.jpg') Muzzle.setMinfilter(Texture.FTLinear) Muzzle.setMagfilter(Texture.FTLinear) MuzzleSurprised = loader.loadTexture( 'phase_3/maps/muzzleShortSurprised.jpg') MuzzleSurprised.setMinfilter(Texture.FTLinear) MuzzleSurprised.setMagfilter(Texture.FTLinear) LeftA = Point3(0.06, 0.0, 0.14) LeftB = Point3(-0.13, 0.0, 0.1) LeftC = Point3(-0.05, 0.0, 0.0) LeftD = Point3(0.06, 0.0, 0.0) RightA = Point3(0.13, 0.0, 0.1) RightB = Point3(-0.06, 0.0, 0.14) RightC = Point3(-0.06, 0.0, 0.0) RightD = Point3(0.05, 0.0, 0.0) LeftAD = Point3( LeftA[0] - LeftA[2] * (LeftD[0] - LeftA[0]) / (LeftD[2] - LeftA[2]), 0.0, 0.0) LeftBC = Point3( LeftB[0] - LeftB[2] * (LeftC[0] - LeftB[0]) / (LeftC[2] - LeftB[2]), 0.0, 0.0) RightAD = Point3( RightA[0] - RightA[2] * (RightD[0] - RightA[0]) / (RightD[2] - RightA[2]), 0.0, 0.0) RightBC = Point3( RightB[0] - RightB[2] * (RightC[0] - RightB[0]) / (RightC[2] - RightB[2]), 0.0, 0.0) def __init__(self): Actor.Actor.__init__(self) self.toonName = 'ToonHead-' + str(self.this) self.__blinkName = 'blink-' + self.toonName self.__stareAtName = 'stareAt-' + self.toonName self.__lookName = 'look-' + self.toonName self.lookAtTrack = None self.__muzzles = [] self.__surpriseMuzzles = [] self.__angryMuzzles = [] self.__sadMuzzles = [] self.__smileMuzzles = [] self.__laughMuzzles = [] self.__eyes = None self.__eyelashOpen = None self.__eyelashClosed = None self.__lod500Eyes = None self.__lod250Eyes = None self.__lpupil = None self.__lod500lPupil = None self.__lod250lPupil = None self.__rpupil = None self.__lod500rPupil = None self.__lod250rPupil = None self.__muzzle = None self.__eyesOpen = ToonHead.EyesOpen self.__eyesClosed = ToonHead.EyesClosed self.__height = 0.0 self.__eyelashesHiddenByGlasses = False self.randGen = random.Random() self.randGen.seed(random.random()) self.eyelids = ClassicFSM('eyelids', [ State('off', self.enterEyelidsOff, self.exitEyelidsOff, ['open', 'closed', 'surprised']), State('open', self.enterEyelidsOpen, self.exitEyelidsOpen, ['closed', 'surprised', 'off']), State('surprised', self.enterEyelidsSurprised, self.exitEyelidsSurprised, ['open', 'closed', 'off']), State('closed', self.enterEyelidsClosed, self.exitEyelidsClosed, ['open', 'surprised', 'off']) ], 'off', 'off') self.eyelids.enterInitialState() self.emote = None self.__stareAtNode = NodePath() self.__defaultStarePoint = Point3(0, 0, 0) self.__stareAtPoint = self.__defaultStarePoint self.__stareAtTime = 0 self.lookAtPositionCallbackArgs = None def delete(self): try: self.ToonHead_deleted except: self.ToonHead_deleted = 1 taskMgr.remove(self.__blinkName) taskMgr.remove(self.__lookName) taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None del self.eyelids del self.__stareAtNode del self.__stareAtPoint if self.__eyes: del self.__eyes if self.__lpupil: del self.__lpupil if self.__rpupil: del self.__rpupil if self.__eyelashOpen: del self.__eyelashOpen if self.__eyelashClosed: del self.__eyelashClosed self.lookAtPositionCallbackArgs = None Actor.Actor.delete(self) return def setupHead(self, dna, forGui=0): self.__height = self.generateToonHead(dna, forGui=forGui) self.generateToonColor(dna) animalStyle = dna.getAnimal() bodyScale = toonBodyScales[animalStyle] headScale = toonHeadScales[animalStyle] self.getGeomNode().setScale(headScale[0] * bodyScale * 1.3, headScale[1] * bodyScale * 1.3, headScale[2] * bodyScale * 1.3) if forGui: self.getGeomNode().setDepthWrite(1) self.getGeomNode().setDepthTest(1) if dna.getAnimal() == 'dog': self.loop('neutral') def fitAndCenterHead(self, maxDim, forGui=0): p1 = Point3() p2 = Point3() self.calcTightBounds(p1, p2) if forGui: h = 180 t = p1[0] p1.setX(-p2[0]) p2.setX(-t) else: h = 0 d = p2 - p1 biggest = max(d[0], d[2]) s = maxDim / biggest mid = (p1 + d / 2.0) * s self.setPosHprScale(-mid[0], -mid[1] + 1, -mid[2], h, 0, 0, s, s, s) def setLookAtPositionCallbackArgs(self, argTuple): self.lookAtPositionCallbackArgs = argTuple def getHeight(self): return self.__height def getRandomForwardLookAtPoint(self): x = self.randGen.choice((-0.8, -0.5, 0, 0.5, 0.8)) z = self.randGen.choice((-0.5, 0, 0.5, 0.8)) return Point3(x, 1.5, z) def findSomethingToLookAt(self): if self.lookAtPositionCallbackArgs is not None: pnt = self.lookAtPositionCallbackArgs[0].getLookAtPosition( self.lookAtPositionCallbackArgs[1], self.lookAtPositionCallbackArgs[2]) self.startStareAt(self, pnt) return if self.randGen.random() < 0.33: lookAtPnt = self.getRandomForwardLookAtPoint() else: lookAtPnt = self.__defaultStarePoint self.lerpLookAt(lookAtPnt, blink=1) return def generateToonHead(self, style, lods=['1000'], forGui=0): headStyle = style.head fix = None if headStyle == 'dls': filePrefix = HeadDict['dls'] headHeight = 0.75 elif headStyle == 'dss': filePrefix = HeadDict['dss'] headHeight = 0.5 elif headStyle == 'dsl': filePrefix = HeadDict['dsl'] headHeight = 0.5 elif headStyle == 'dll': filePrefix = HeadDict['dll'] headHeight = 0.75 elif headStyle == 'cls': filePrefix = HeadDict['c'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'css': filePrefix = HeadDict['c'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'csl': filePrefix = HeadDict['c'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'cll': filePrefix = HeadDict['c'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'hls': filePrefix = HeadDict['h'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'hss': filePrefix = HeadDict['h'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'hsl': filePrefix = HeadDict['h'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'hll': filePrefix = HeadDict['h'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'mls': filePrefix = HeadDict['m'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'mss': filePrefix = HeadDict['m'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'rls': filePrefix = HeadDict['r'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'rss': filePrefix = HeadDict['r'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'rsl': filePrefix = HeadDict['r'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'rll': filePrefix = HeadDict['r'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'fls': filePrefix = HeadDict['f'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'fss': filePrefix = HeadDict['f'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'fsl': filePrefix = HeadDict['f'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'fll': filePrefix = HeadDict['f'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'pls': filePrefix = HeadDict['p'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'pss': filePrefix = HeadDict['p'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'psl': filePrefix = HeadDict['p'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'pll': filePrefix = HeadDict['p'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'bls': filePrefix = HeadDict['b'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'bss': filePrefix = HeadDict['b'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'bsl': filePrefix = HeadDict['b'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'bll': filePrefix = HeadDict['b'] fix = self.__fixHeadLongLong headHeight = 0.75 elif headStyle == 'sls': filePrefix = HeadDict['s'] fix = self.__fixHeadLongShort headHeight = 0.75 elif headStyle == 'sss': filePrefix = HeadDict['s'] fix = self.__fixHeadShortShort headHeight = 0.5 elif headStyle == 'ssl': filePrefix = HeadDict['s'] fix = self.__fixHeadShortLong headHeight = 0.5 elif headStyle == 'sll': filePrefix = HeadDict['s'] fix = self.__fixHeadLongLong headHeight = 0.75 else: ToonHead.notify.error('unknown head style: %s' % headStyle) if len(lods) == 1: self.loadModel('phase_3' + filePrefix + lods[0], 'head', 'lodRoot', 1) if fix is not None: fix(style, None, 1) if not forGui: self.__lods = lods self.__style = style self.__headStyle = headStyle self.__copy = 1 else: for lod in lods: self.loadModel('phase_3' + filePrefix + lod, 'head', lod, 1) if fix is not None: fix(style, lod, 1) if not forGui: self.__lods = lods self.__style = style self.__headStyle = headStyle self.__copy = 1 self.__fixEyes(style, forGui) self.setupEyelashes(style) self.eyelids.request('closed') self.eyelids.request('open') self.setupMuzzles(style) return headHeight def hideEars(self): self.findAllMatches('**/ears*;+s').stash() def showEars(self): self.findAllMatches('**/ears*;+s').unstash() def hideEyelashes(self): if self.__eyelashOpen: self.__eyelashOpen.stash() if self.__eyelashClosed: self.__eyelashClosed.stash() self.__eyelashesHiddenByGlasses = True def showEyelashes(self): if self.__eyelashOpen: self.__eyelashOpen.unstash() if self.__eyelashClosed: self.__eyelashClosed.unstash() self.__eyelashesHiddenByGlasses = False def generateToonColor(self, style): parts = self.findAllMatches('**/head*') parts.setColor(style.getHeadColor()) animalType = style.getAnimal() if animalType == 'cat' or animalType == 'rabbit' or animalType == 'bear' or animalType == 'mouse' or animalType == 'pig': parts = self.findAllMatches('**/ear?-*') parts.setColor(style.getHeadColor()) def __fixEyes(self, style, forGui=0): mode = -3 if forGui: mode = -2 if self.hasLOD(): for lodName in self.getLODNames(): self.drawInFront('eyes*', 'head-front*', mode, lodName=lodName) if not self.find('**/joint_pupil*').isEmpty(): self.drawInFront('joint_pupil*', 'eyes*', -1, lodName=lodName) else: self.drawInFront('def_*_pupil', 'eyes*', -1, lodName=lodName) self.__eyes = self.getLOD(1000).find('**/eyes*') self.__lod500Eyes = self.getLOD(500).find('**/eyes*') self.__lod250Eyes = self.getLOD(250).find('**/eyes*') if self.__lod500Eyes.isEmpty(): self.__lod500Eyes = None else: self.__lod500Eyes.setColorOff() if not self.find('**/joint_pupilL*').isEmpty(): self.__lod500lPupil = self.__lod500Eyes.find( '**/joint_pupilL*') self.__lod500rPupil = self.__lod500Eyes.find( '**/joint_pupilR*') else: self.__lod500lPupil = self.__lod500Eyes.find( '**/def_left_pupil*') self.__lod500rPupil = self.__lod500Eyes.find( '**/def_right_pupil*') if self.__lod250Eyes.isEmpty(): self.__lod250Eyes = None else: self.__lod250Eyes.setColorOff() if not self.find('**/joint_pupilL*').isEmpty(): self.__lod250lPupil = self.__lod250Eyes.find( '**/joint_pupilL*') self.__lod250rPupil = self.__lod250Eyes.find( '**/joint_pupilR*') else: self.__lod250lPupil = self.__lod250Eyes.find( '**/def_left_pupil*') self.__lod250rPupil = self.__lod250Eyes.find( '**/def_right_pupil*') else: self.drawInFront('eyes*', 'head-front*', mode) if not self.find('joint_pupil*').isEmpty(): self.drawInFront('joint_pupil*', 'eyes*', -1) else: self.drawInFront('def_*_pupil', 'eyes*', -1) self.__eyes = self.find('**/eyes*') if not self.__eyes.isEmpty(): self.__eyes.setColorOff() self.__lpupil = None self.__rpupil = None if not self.find('**/joint_pupilL*').isEmpty(): if self.getLOD(1000): lp = self.getLOD(1000).find('**/joint_pupilL*') rp = self.getLOD(1000).find('**/joint_pupilR*') else: lp = self.find('**/joint_pupilL*') rp = self.find('**/joint_pupilR*') elif not self.getLOD(1000): lp = self.find('**/def_left_pupil*') rp = self.find('**/def_right_pupil*') else: lp = self.getLOD(1000).find('**/def_left_pupil*') rp = self.getLOD(1000).find('**/def_right_pupil*') if lp.isEmpty() or rp.isEmpty(): print('Unable to locate pupils.') else: leye = self.__eyes.attachNewNode('leye') reye = self.__eyes.attachNewNode('reye') lmat = Mat4(0.802174, 0.59709, 0, 0, -0.586191, 0.787531, 0.190197, 0, 0.113565, -0.152571, 0.981746, 0, -0.233634, 0.418062, 0.0196875, 1) leye.setMat(lmat) rmat = Mat4(0.786788, -0.617224, 0, 0, 0.602836, 0.768447, 0.214658, 0, -0.132492, -0.16889, 0.976689, 0, 0.233634, 0.418062, 0.0196875, 1) reye.setMat(rmat) self.__lpupil = leye.attachNewNode('lpupil') self.__rpupil = reye.attachNewNode('rpupil') lpt = self.__eyes.attachNewNode('') rpt = self.__eyes.attachNewNode('') lpt.wrtReparentTo(self.__lpupil) rpt.wrtReparentTo(self.__rpupil) lp.reparentTo(lpt) rp.reparentTo(rpt) self.__lpupil.adjustAllPriorities(1) self.__rpupil.adjustAllPriorities(1) if self.__lod500Eyes: self.__lod500lPupil.adjustAllPriorities(1) self.__lod500rPupil.adjustAllPriorities(1) if self.__lod250Eyes: self.__lod250lPupil.adjustAllPriorities(1) self.__lod250rPupil.adjustAllPriorities(1) animalType = style.getAnimal() if animalType != 'dog': self.__lpupil.flattenStrong() self.__rpupil.flattenStrong() def __setPupilDirection(self, x, y): if y < 0.0: y2 = -y left1 = self.LeftAD + (self.LeftD - self.LeftAD) * y2 left2 = self.LeftBC + (self.LeftC - self.LeftBC) * y2 right1 = self.RightAD + (self.RightD - self.RightAD) * y2 right2 = self.RightBC + (self.RightC - self.RightBC) * y2 else: y2 = y left1 = self.LeftAD + (self.LeftA - self.LeftAD) * y2 left2 = self.LeftBC + (self.LeftB - self.LeftBC) * y2 right1 = self.RightAD + (self.RightA - self.RightAD) * y2 right2 = self.RightBC + (self.RightB - self.RightBC) * y2 left0 = Point3( 0.0, 0.0, left1[2] - left1[0] * (left2[2] - left1[2]) / (left2[0] - left1[0])) right0 = Point3( 0.0, 0.0, right1[2] - right1[0] * (right2[2] - right1[2]) / (right2[0] - right1[0])) if x < 0.0: x2 = -x left = left0 + (left2 - left0) * x2 right = right0 + (right2 - right0) * x2 else: x2 = x left = left0 + (left1 - left0) * x2 right = right0 + (right1 - right0) * x2 self.__lpupil.setPos(left) self.__rpupil.setPos(right) def __lookPupilsAt(self, node, point): if node is not None: mat = node.getMat(self.__eyes) point = mat.xformPoint(point) distance = 1.0 recip_z = 1.0 / max(0.1, point[1]) x = distance * point[0] * recip_z y = distance * point[2] * recip_z x = min(max(x, -1), 1) y = min(max(y, -1), 1) self.__setPupilDirection(x, y) def __lookHeadAt(self, node, point, frac=1.0, lod=None): reachedTarget = 1 if lod is None: head = self.getPart('head', self.getLODNames()[0]) else: head = self.getPart('head', lod) if node is not None: headParent = head.getParent() mat = node.getMat(headParent) point = mat.xformPoint(point) rot = Mat3(0, 0, 0, 0, 0, 0, 0, 0, 0) lookAt(rot, Vec3(point), Vec3(0, 0, 1), CSDefault) scale = VBase3(0, 0, 0) hpr = VBase3(0, 0, 0) if decomposeMatrix(rot, scale, hpr, CSDefault): hpr = VBase3(min(max(hpr[0], -60), 60), min(max(hpr[1], -20), 30), 0) if frac != 1: currentHpr = head.getHpr() reachedTarget = abs(hpr[0] - currentHpr[0]) < 1.0 and abs( hpr[1] - currentHpr[1]) < 1.0 hpr = currentHpr + (hpr - currentHpr) * frac if lod is None: for lodName in self.getLODNames(): head = self.getPart('head', lodName) head.setHpr(hpr) else: head.setHpr(hpr) return reachedTarget def setupEyelashes(self, style): if style.getGender() == 'm': if self.__eyelashOpen: self.__eyelashOpen.removeNode() self.__eyelashOpen = None if self.__eyelashClosed: self.__eyelashClosed.removeNode() self.__eyelashClosed = None else: if self.__eyelashOpen: self.__eyelashOpen.removeNode() if self.__eyelashClosed: self.__eyelashClosed.removeNode() animal = style.head[0] model = loader.loadModel('phase_3' + EyelashDict[animal]) if self.hasLOD(): head = self.getPart('head', '1000') else: head = self.getPart('head', 'lodRoot') length = style.head[1] if length == 'l': openString = 'open-long' closedString = 'closed-long' else: openString = 'open-short' closedString = 'closed-short' self.__eyelashOpen = model.find('**/' + openString).copyTo(head) self.__eyelashClosed = model.find('**/' + closedString).copyTo(head) model.removeNode() def __fixHeadLongLong(self, style, lodName=None, copy=1): if lodName is None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) otherParts = searchRoot.findAllMatches('**/*short*') for partNum in range(0, otherParts.getNumPaths()): if copy: otherParts.getPath(partNum).removeNode() else: otherParts.getPath(partNum).stash() def __fixHeadLongShort(self, style, lodName=None, copy=1): animalType = style.getAnimal() if lodName is None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) if animalType != 'duck' and animalType != 'horse': if animalType == 'rabbit': if copy: searchRoot.find('**/ears-long').removeNode() else: searchRoot.find('**/ears-long').hide() elif copy: searchRoot.find('**/ears-short').removeNode() else: searchRoot.find('**/ears-short').hide() if animalType != 'rabbit': if copy: searchRoot.find('**/eyes-short').removeNode() else: searchRoot.find('**/eyes-short').hide() if animalType != 'dog': if copy: searchRoot.find('**/joint_pupilL_short').removeNode() searchRoot.find('**/joint_pupilR_short').removeNode() else: searchRoot.find('**/joint_pupilL_short').stash() searchRoot.find('**/joint_pupilR_short').stash() if copy: self.find('**/head-short').removeNode() self.find('**/head-front-short').removeNode() else: self.find('**/head-short').hide() self.find('**/head-front-short').hide() if animalType != 'rabbit': muzzleParts = searchRoot.findAllMatches('**/muzzle-long*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() else: muzzleParts = searchRoot.findAllMatches('**/muzzle-short*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() def __fixHeadShortLong(self, style, lodName=None, copy=1): animalType = style.getAnimal() if lodName is None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) if animalType != 'duck' and animalType != 'horse': if animalType == 'rabbit': if copy: searchRoot.find('**/ears-short').removeNode() else: searchRoot.find('**/ears-short').hide() elif copy: searchRoot.find('**/ears-long').removeNode() else: searchRoot.find('**/ears-long').hide() if animalType != 'rabbit': if copy: searchRoot.find('**/eyes-long').removeNode() else: searchRoot.find('**/eyes-long').hide() if animalType != 'dog': if copy: searchRoot.find('**/joint_pupilL_long').removeNode() searchRoot.find('**/joint_pupilR_long').removeNode() else: searchRoot.find('**/joint_pupilL_long').stash() searchRoot.find('**/joint_pupilR_long').stash() if copy: searchRoot.find('**/head-long').removeNode() searchRoot.find('**/head-front-long').removeNode() else: searchRoot.find('**/head-long').hide() searchRoot.find('**/head-front-long').hide() if animalType != 'rabbit': muzzleParts = searchRoot.findAllMatches('**/muzzle-short*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() else: muzzleParts = searchRoot.findAllMatches('**/muzzle-long*') for partNum in range(0, muzzleParts.getNumPaths()): if copy: muzzleParts.getPath(partNum).removeNode() else: muzzleParts.getPath(partNum).hide() def __fixHeadShortShort(self, style, lodName=None, copy=1): if lodName is None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) otherParts = searchRoot.findAllMatches('**/*long*') for partNum in range(0, otherParts.getNumPaths()): if copy: otherParts.getPath(partNum).removeNode() else: otherParts.getPath(partNum).stash() def __blinkOpenEyes(self, task): if self.eyelids.getCurrentState().getName() == 'closed': self.eyelids.request('open') r = self.randGen.random() if r < 0.1: t = 0.2 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self.__blinkCloseEyes, self.__blinkName) return task.done def __blinkCloseEyes(self, task): if self.eyelids.getCurrentState().getName() != 'open': taskMgr.doMethodLater(4.0, self.__blinkCloseEyes, self.__blinkName) else: self.eyelids.request('closed') taskMgr.doMethodLater(0.125, self.__blinkOpenEyes, self.__blinkName) return task.done def startBlink(self): taskMgr.remove(self.__blinkName) if self.__eyes: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self.__blinkCloseEyes, self.__blinkName) def stopBlink(self): taskMgr.remove(self.__blinkName) if self.__eyes: self.eyelids.request('open') def closeEyes(self): self.eyelids.request('closed') def openEyes(self): self.eyelids.request('open') def surpriseEyes(self): self.eyelids.request('surprised') def sadEyes(self): self.__eyesOpen = ToonHead.EyesSadOpen self.__eyesClosed = ToonHead.EyesSadClosed def angryEyes(self): self.__eyesOpen = ToonHead.EyesAngryOpen self.__eyesClosed = ToonHead.EyesAngryClosed def normalEyes(self): self.__eyesOpen = ToonHead.EyesOpen self.__eyesClosed = ToonHead.EyesClosed def blinkEyes(self): taskMgr.remove(self.__blinkName) self.eyelids.request('closed') taskMgr.doMethodLater(0.1, self.__blinkOpenEyes, self.__blinkName) def __stareAt(self, task): frac = 2 * globalClock.getDt() reachedTarget = self.__lookHeadAt(self.__stareAtNode, self.__stareAtPoint, frac) self.__lookPupilsAt(self.__stareAtNode, self.__stareAtPoint) if reachedTarget and self.__stareAtNode is None: return task.done return task.cont def doLookAroundToStareAt(self, node, point): self.startStareAt(node, point) self.startLookAround() def startStareAtHeadPoint(self, point): self.startStareAt(self, point) def startStareAt(self, node, point): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None self.__stareAtNode = node if point is not None: self.__stareAtPoint = point else: self.__stareAtPoint = self.__defaultStarePoint self.__stareAtTime = globalClock.getFrameTime() taskMgr.add(self.__stareAt, self.__stareAtName) def lerpLookAt(self, point, time=1.0, blink=0): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None lodNames = self.getLODNames() if lodNames: lodName = lodNames[0] else: return 0 head = self.getPart('head', lodName) startHpr = head.getHpr() startLpupil = self.__lpupil.getPos() startRpupil = self.__rpupil.getPos() self.__lookHeadAt(None, point, lod=lodName) self.__lookPupilsAt(None, point) endHpr = head.getHpr() endLpupil = self.__lpupil.getPos() * 0.5 endRpupil = self.__rpupil.getPos() * 0.5 head.setHpr(startHpr) self.__lpupil.setPos(startLpupil) self.__rpupil.setPos(startRpupil) if startHpr.almostEqual(endHpr, 10): return 0 if blink: self.blinkEyes() lookToTgt_TimeFraction = 0.2 lookToTgtTime = time * lookToTgt_TimeFraction returnToEyeCenterTime = time - lookToTgtTime - 0.5 origin = Point3(0, 0, 0) blendType = 'easeOut' self.lookAtTrack = Parallel(Sequence( LerpPosInterval(self.__lpupil, lookToTgtTime, endLpupil, blendType=blendType), Wait(0.5), LerpPosInterval(self.__lpupil, returnToEyeCenterTime, origin, blendType=blendType)), Sequence( LerpPosInterval(self.__rpupil, lookToTgtTime, endRpupil, blendType=blendType), Wait(0.5), LerpPosInterval(self.__rpupil, returnToEyeCenterTime, origin, blendType=blendType)), name=self.__stareAtName) for lodName in self.getLODNames(): head = self.getPart('head', lodName) self.lookAtTrack.append( LerpHprInterval(head, time, endHpr, blendType='easeInOut')) self.lookAtTrack.start() return 1 def stopStareAt(self): self.lerpLookAt(Vec3.forward()) def stopStareAtNow(self): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None if self.__lpupil and self.__rpupil: self.__setPupilDirection(0, 0) for lodName in self.getLODNames(): head = self.getPart('head', lodName) head.setHpr(0, 0, 0) def __lookAround(self, task): self.findSomethingToLookAt() t = self.randGen.random() * 4.0 + 3.0 taskMgr.doMethodLater(t, self.__lookAround, self.__lookName) return task.done def startLookAround(self): taskMgr.remove(self.__lookName) t = self.randGen.random() * 5.0 + 2.0 taskMgr.doMethodLater(t, self.__lookAround, self.__lookName) def stopLookAround(self): taskMgr.remove(self.__lookName) self.stopStareAt() def stopLookAroundNow(self): taskMgr.remove(self.__lookName) self.stopStareAtNow() def enterEyelidsOff(self): pass def exitEyelidsOff(self): pass def enterEyelidsOpen(self): if not self.__eyes.isEmpty(): self.__eyes.setTexture(self.__eyesOpen, 1) if self.__eyelashOpen: self.__eyelashOpen.show() if self.__eyelashClosed: self.__eyelashClosed.hide() if self.__lod500Eyes: self.__lod500Eyes.setTexture(self.__eyesOpen, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(self.__eyesOpen, 1) if self.__lpupil: self.__lpupil.show() self.__rpupil.show() if self.__lod500lPupil: self.__lod500lPupil.show() self.__lod500rPupil.show() if self.__lod250lPupil: self.__lod250lPupil.show() self.__lod250rPupil.show() def exitEyelidsOpen(self): pass def enterEyelidsClosed(self): if not self.__eyes.isEmpty() and self.__eyesClosed: self.__eyes.setTexture(self.__eyesClosed, 1) if self.__eyelashOpen: self.__eyelashOpen.hide() if self.__eyelashClosed: self.__eyelashClosed.show() if self.__lod500Eyes: self.__lod500Eyes.setTexture(self.__eyesClosed, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(self.__eyesClosed, 1) if self.__lpupil: self.__lpupil.hide() self.__rpupil.hide() if self.__lod500lPupil: self.__lod500lPupil.hide() self.__lod500rPupil.hide() if self.__lod250lPupil: self.__lod250lPupil.hide() self.__lod250rPupil.hide() def exitEyelidsClosed(self): pass def enterEyelidsSurprised(self): if not self.__eyes.isEmpty() and ToonHead.EyesSurprised: self.__eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__eyelashOpen: self.__eyelashOpen.hide() if self.__eyelashClosed: self.__eyelashClosed.hide() if self.__lod500Eyes: self.__lod500Eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__muzzle: self.__muzzle.setTexture(ToonHead.MuzzleSurprised, 1) if self.__lpupil: self.__lpupil.show() self.__rpupil.show() if self.__lod500lPupil: self.__lod500lPupil.show() self.__lod500rPupil.show() if self.__lod250lPupil: self.__lod250lPupil.show() self.__lod250rPupil.show() def exitEyelidsSurprised(self): if self.__muzzle: self.__muzzle.setTexture(ToonHead.Muzzle, 1) def setupMuzzles(self, style): self.__muzzles = [] self.__surpriseMuzzles = [] self.__angryMuzzles = [] self.__sadMuzzles = [] self.__smileMuzzles = [] self.__laughMuzzles = [] def hideAddNonEmptyItemToList(item, list): if not item.isEmpty(): item.hide() list.append(item) if self.hasLOD(): for lodName in self.getLODNames(): animal = style.getAnimal() if animal != 'dog': muzzle = self.find('**/' + lodName + '/**/muzzle*neutral') else: muzzle = self.find('**/' + lodName + '/**/muzzle*') if lodName == '1000' or lodName == '500': filePrefix = DogMuzzleDict[style.head] muzzles = loader.loadModel('phase_3' + filePrefix + lodName) if not self.find( '**/' + lodName + '/**/__Actor_head/def_head').isEmpty(): muzzles.reparentTo( self.find('**/' + lodName + '/**/__Actor_head/def_head')) else: muzzles.reparentTo( self.find('**/' + lodName + '/**/joint_toHead')) surpriseMuzzle = self.find('**/' + lodName + '/**/muzzle*surprise') angryMuzzle = self.find('**/' + lodName + '/**/muzzle*angry') sadMuzzle = self.find('**/' + lodName + '/**/muzzle*sad') smileMuzzle = self.find('**/' + lodName + '/**/muzzle*smile') laughMuzzle = self.find('**/' + lodName + '/**/muzzle*laugh') self.__muzzles.append(muzzle) hideAddNonEmptyItemToList(surpriseMuzzle, self.__surpriseMuzzles) hideAddNonEmptyItemToList(angryMuzzle, self.__angryMuzzles) hideAddNonEmptyItemToList(sadMuzzle, self.__sadMuzzles) hideAddNonEmptyItemToList(smileMuzzle, self.__smileMuzzles) hideAddNonEmptyItemToList(laughMuzzle, self.__laughMuzzles) else: if style.getAnimal() != 'dog': muzzle = self.find('**/muzzle*neutral') else: muzzle = self.find('**/muzzle*') filePrefix = DogMuzzleDict[style.head] muzzles = loader.loadModel('phase_3' + filePrefix + '1000') if not self.find('**/def_head').isEmpty(): muzzles.reparentTo(self.find('**/def_head')) else: muzzles.reparentTo(self.find('**/joint_toHead')) surpriseMuzzle = self.find('**/muzzle*surprise') angryMuzzle = self.find('**/muzzle*angry') sadMuzzle = self.find('**/muzzle*sad') smileMuzzle = self.find('**/muzzle*smile') laughMuzzle = self.find('**/muzzle*laugh') self.__muzzles.append(muzzle) hideAddNonEmptyItemToList(surpriseMuzzle, self.__surpriseMuzzles) hideAddNonEmptyItemToList(angryMuzzle, self.__angryMuzzles) hideAddNonEmptyItemToList(sadMuzzle, self.__sadMuzzles) hideAddNonEmptyItemToList(smileMuzzle, self.__smileMuzzles) hideAddNonEmptyItemToList(laughMuzzle, self.__laughMuzzles) def getMuzzles(self): return self.__muzzles def getSurpriseMuzzles(self): return self.__surpriseMuzzles def getAngryMuzzles(self): return self.__angryMuzzles def getSadMuzzles(self): return self.__sadMuzzles def getSmileMuzzles(self): return self.__smileMuzzles def getLaughMuzzles(self): return self.__laughMuzzles def showNormalMuzzle(self): for muzzleNum in range(len(self.__muzzles)): self.__muzzles[muzzleNum].show() def hideNormalMuzzle(self): for muzzleNum in range(len(self.__muzzles)): self.__muzzles[muzzleNum].hide() def showAngryMuzzle(self): for muzzleNum in range(len(self.__angryMuzzles)): self.__angryMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideAngryMuzzle(self): for muzzleNum in range(len(self.__angryMuzzles)): self.__angryMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSadMuzzle(self): for muzzleNum in range(len(self.__sadMuzzles)): self.__sadMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSadMuzzle(self): for muzzleNum in range(len(self.__sadMuzzles)): self.__sadMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSmileMuzzle(self): for muzzleNum in range(len(self.__smileMuzzles)): self.__smileMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSmileMuzzle(self): for muzzleNum in range(len(self.__smileMuzzles)): self.__smileMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showLaughMuzzle(self): for muzzleNum in range(len(self.__laughMuzzles)): self.__laughMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideLaughMuzzle(self): for muzzleNum in range(len(self.__laughMuzzles)): self.__laughMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSurpriseMuzzle(self): for muzzleNum in range(len(self.__surpriseMuzzles)): self.__surpriseMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSurpriseMuzzle(self): for muzzleNum in range(len(self.__surpriseMuzzles)): self.__surpriseMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show()
class Human(HumanBase.HumanBase, Biped.Biped): notify = DirectNotifyGlobal.directNotify.newCategory("Human") prebuiltAnimData = {} def __init__(self, other=None): Biped.Biped.__init__(self, other, HumanAnimationMixer) self.zombie = False self.crazyColorSkin = False self.crazyColorSkinIndex = 0 self.flattenPending = None self.flattenSuperLowName = None self.optimizeLOD = base.config.GetBool("optimize-avatar-lod", 1) self.loaded = 0 self.playingRate = None self.shadowFileName = "models/misc/drop_shadow" self.setFont(PiratesGlobals.getInterfaceFont()) self._Human__blinkName = "blink-" + str(self.this) self.eyeLids = None self.eyeBalls = None self.eyeIris = None self.reducedAnimList = None self.headNode = None self.headEffects = NodePath("headEffects") self.extraNode = None self.scaleNode = None self.rootNode = None self.floorOffsetZ = 0.0 self.isGhost = 0 self.headFudgeHpr = Vec3(0, 0, 0) self.randGen = random.Random() self.randGen.seed(random.random()) self.eyeFSM = ClassicFSM( "eyeFSM", [ State("off", self.enterEyeFSMOff, self.exitEyeFSMOff, ["open", "closed"]), State("open", self.enterEyeFSMOpen, self.exitEyeFSMOpen, ["closed", "off"]), State("closed", self.enterEyeFSMClosed, self.exitEyeFSMClosed, ["open", "off"]), ], "off", "off", ) self.eyeFSM.enterInitialState() if other != None: self.copyHuman(other) def removeCopiedNodes(self): self.dropShadow = self.find("**/drop_shadow*") if not self.dropShadow.isEmpty(): self.deleteDropShadow() else: self.dropShadow = None billboardNode = self.find("**/billboardNode") if not billboardNode.isEmpty(): billboardNode.removeNode() self.getGeomNode().getParent().removeNode() def flattenHuman(self): self.getWeaponJoints() def flattenSuperLow(self): name = "flattenSuperLow-%s" % self.this self.flattenSuperLowName = name model = self.getLOD("500") self.accept(name, self._Human__doneFlattenSuperLow) taskMgr.remove(name) taskMgr.add(self.flattenSuperLowTask, name, extraArgs=[model], taskChain="background") def flattenSuperLowTask(self, model): model = model.copyTo(NodePath()) rhn = model.find("**/rightHand") lhn = model.find("**/leftHand") if lhn: lhn.detachNode() if rhn: rhn.detachNode() node = model.node() gr = SceneGraphReducer() model.node().setAttrib(TransparencyAttrib.make(0), 2000) gr.applyAttribs( node, SceneGraphReducer.TTApplyTextureColor | SceneGraphReducer.TTTexMatrix | SceneGraphReducer.TTOther | SceneGraphReducer.TTCullFace | SceneGraphReducer.TTTransform | SceneGraphReducer.TTColor | SceneGraphReducer.TTColorScale, ) num_removed = gr.flatten(node, -1) gr.makeCompatibleState(node) gr.collectVertexData( node, ~(SceneGraphReducer.CVDFormat | SceneGraphReducer.CVDName | SceneGraphReducer.CVDAnimationType) ) gr.unify(node, 0) name = self.flattenSuperLowName if name: messenger.send(name, [model], taskChain="default") def _Human__doneFlattenSuperLow(self, flat): self.headNode = flat.find("**/def_head01") self.rootNode = flat.find("**/dx_root") self.getWeaponJoints() orig = self.getLOD("500") orig.getChildren().detach() self.loadModel(flat, lodName="500", copy=False, autoBindAnims=False) self.getWeaponJoints() if hasattr(self, "animProp") and self.animProp: self.resetAnimProp() self.findAllMatches("**/def_head01").detach() self.findAllMatches("**/dx_root").detach() for lodName in self.getLODNames(): if lodName == "500": self.headNode.reparentTo(self.getLOD(lodName).find("**/+Character")) self.rootNode.reparentTo(self.getLOD(lodName).find("**/+Character")) continue self.headNode.instanceTo(self.getLOD(lodName).find("**/+Character")) self.rootNode.instanceTo(self.getLOD(lodName).find("**/+Character")) self.headEffects.reparentTo(self.headNode) def _Human__doneFlattenHuman(self, models): self.flattenPending = None self.getWeaponJoints() def copyHuman(self, other): self.gender = other.gender self.loaded = other.loaded self.loadAnimatedHead = other.loadAnimatedHead self.rootScale = other.rootScale def delete(self): try: pass except: self.Human_deleted = 1 taskMgr.remove(self._Human__blinkName) name = self.flattenSuperLowName if name: self.flattenSuperLowName = None self.ignore(name) taskMgr.remove(name) if self.dropShadow and not self.dropShadow.isEmpty(): self.deleteDropShadow() del self.eyeFSM self.controlShapes = None self.sliderNames = None Biped.Biped.delete(self) def isDeleted(self): try: if self.Human_deleted == 1: return True except: return False def fixEyes(self): self.eyeLids = {} self.eyeBalls = {} self.eyeIris = {} for lodName in self.getLODNames(): geom = self.getPart("head", lodName) self.eyeLids[lodName] = geom.findAllMatches("**/*eyelid*") self.eyeBalls[lodName] = geom.findAllMatches("**/eye_ball*") self.eyeIris[lodName] = geom.findAllMatches("**/eye_iris*") self.eyeLids[lodName].stash() self.eyeBalls[lodName].unstash() self.eyeIris[lodName].unstash() def makeAnimDict(self, gender, animNames): self.animTable = [] for currAnim in animNames: anim = animNames.get(currAnim) for currAnimName in anim: self.animTable.append([currAnimName, currAnimName]) self.reducedAnimList = self.animTable def forceLoadAnimDict(self): for anim in self.animDict.keys(): self.getAnimControls(anim) def createAnimDict(self, customList=None): filePrefix = "models/char/m" genderPrefix = "m" if self.style.gender == "f": self.type = BodyDefs.femaleFrames[self.style.getBodyShape()] filePrefix = "models/char/f" genderPrefix = "f" else: self.type = BodyDefs.maleFrames[self.style.getBodyShape()] if self.reducedAnimList is None: self.animDict = self.prebuiltAnimData[genderPrefix + self.type] return None filePrefix += "p" animList = self.reducedAnimList self.animDict = {} for anim in animList: animSuffix = "" for i in range(0, len(CustomAnimDict[genderPrefix + self.type])): if anim[0] == CustomAnimDict[genderPrefix + self.type][i]: animSuffix = "_" + genderPrefix + NewModelDict.get(self.type) break continue self.animDict[anim[0]] = filePrefix + "_" + anim[1] + animSuffix return filePrefix def getIsPaid(self): return True def setupGhostNodes(self): lod = NodePath(self.getLODNode()) for node in lod.getChildren(): eyes = node.findAllMatches("**/eye*") if eyes: eyes.wrtReparentTo(eyes[0].getParent().attachNewNode(ModelNode("eyes"))) continue def loadHuman(self, other): other.style = self.style other.gender = self.style.gender other.model.dna = self.style self.createAnimDict() if self.style.gender == "f": self.headFudgeHpr = Vec3(0, 0, 0) idx = 1 else: self.headFudgeHpr = Vec3(0, 0, 0) idx = 0 other.zombie = self.zombie other.crazyColorSkin = self.crazyColorSkin other.setCrazyColorSkinIndex(self.getCrazyColorSkinIndex()) yieldThread("anim dict") other.isPaid = self.getIsPaid() other.showLOD(2000) yieldThread("showLOD") base.loadingScreen.tick() if other.zombie: other.showZombie() if hasattr(self, "motionFSM"): self.motionFSM.setAvatar(self) base.loadingScreen.tick() yieldThread("zombie") other.applyBodyShaper() base.loadingScreen.tick() yieldThread("body shaper") base.loadingScreen.tick() other.applyHeadShaper() yieldThread("head shaper") base.loadingScreen.tick() if self.zombie == 2: other.model.eyeBalls.unstash() other.model.irises.stash() elif self.zombie: other.model.eyeBalls.stash() other.model.irises.stash() else: other.model.eyeBalls.unstash() other.model.irises.unstash() base.loadingScreen.tick() self.copyActor(other) base.loadingScreen.tick() self.floorOffsetZ = other.rootNode.getZ() yieldThread("copyActor") self.copyHuman(other) if self.isGhost: self.setupGhostNodes() gnodes = self.getLOD("500").findAllMatches("**/+GeomNode") for node in gnodes: node.setTextureOff(other.model.tattooStage) base.loadingScreen.tick() self.flattenSuperLow() self.rootNode = self.getLOD("500").find("**/dx_root") self.headNode = self.getLOD("500").find("**/def_head01") lodNames = self.getLODNames() self.scaleNode = self.controlJoint(None, "legs", "def_scale_jt", lodNames[0]) if len(lodNames) > 1: for i in range(1, len(lodNames)): self.controlJoint(self.scaleNode, "legs", "def_scale_jt", lodNames[i]) self.setGlobalScale(self.calcBodyScale()) yieldThread("copyHuman") base.loadingScreen.tick() self.loadAnimsOnAllLODs(self.animDict, "modelRoot") base.loadingScreen.tick() yieldThread("loadAnims") other.zombie = 0 other.crazyColorSkin = 0 other.setCrazyColorSkinIndex(0) other.showNormal() yieldThread("show normal") self.initializeNametag3d() self.initializeDropShadow() self.setName(self.getName()) yieldThread("misc nodes") base.loadingScreen.tick() self.loaded = 1 def setGlobalScale(self, scale): self.scaleNode.setScale(scale) self.rootScale = scale self.scaleNode.setZ(-(self.floorOffsetZ * (1 - scale))) def initializeMiscNodes(self): self.initializeNametag3d() self.initializeDropShadow() def undoControlJoints(self): self.getGeomNode().getParent().findAllMatches("def_*").detach() self.getGeomNode().getParent().findAllMatches("trs_*").detach() self.findAllMatches("def_*").detach() self.findAllMatches("trs_*").detach() def cleanupHuman(self, gender="m"): self.eyeFSM.request("off") self.undoControlJoints() self.removeCopiedNodes() self.eyeLids = {} self.eyeBalls = {} self.eyeIris = {} self.flush() self.loaded = 0 self.master = 0 def getCrazyColorSkinIndex(self): return self.crazyColorSkinIndex def setCrazyColorSkinIndex(self, index): if len(HumanDNA.crazySkinColors) > index: self.crazyColorSkinIndex = index else: self.notify.warning( "(Human)index: %d is out of bounds for crazyColorSkin: %d" % (index, len(HumanDNA.crazySkinColors)) ) def generateHuman(self, gender, others, useFaceTex=False): parent = self.getParent() self.detachNode() if gender == "f": other = others[1] else: other = others[0] if self.loaded: self.cleanupHuman() other.useFaceTex = useFaceTex self.loadHuman(other) if self.isLocal(): self.renderReflection = True self.setRenderReflection() self.resetEffectParent() self.enableMixing() self.reparentTo(parent) def getShadowJoint(self): return self.nametagNodePath def getNametagJoints(self): joints = [] for lodName in self.getLODNames(): bundle = self.getPartBundle("modelRoot", lodName) joint = bundle.findChild("name_tag") if joint: joints.append(joint) continue return joints def _Human__blinkOpenEyes(self, task): if self.eyeFSM.getCurrentState().getName() == "closed": self.eyeFSM.request("open") r = self.randGen.random() if r < 0.10000000000000001: t = 0.20000000000000001 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self._Human__blinkCloseEyes, self._Human__blinkName) return Task.done def _Human__blinkCloseEyes(self, task): if self.eyeFSM.getCurrentState().getName() != "open": taskMgr.doMethodLater(4.0, self._Human__blinkCloseEyes, self._Human__blinkName) else: self.eyeFSM.request("closed") taskMgr.doMethodLater(0.125, self._Human__blinkOpenEyes, self._Human__blinkName) return Task.done def startBlink(self): taskMgr.remove(self._Human__blinkName) if self.eyeLids: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self._Human__blinkCloseEyes, self._Human__blinkName) def stopBlink(self): taskMgr.remove(self._Human__blinkName) if self.eyeLids: self.eyeFSM.request("open") def closeEyes(self): self.eyeFSM.request("closed") def openEyes(self): self.eyeFSM.request("open") def enterEyeFSMOff(self): pass def exitEyeFSMOff(self): pass def enterEyeFSMOpen(self): for lodName in self.getLODNames(): self.eyeLids[lodName].hide() self.eyeBalls[lodName].show() self.eyeIris[lodName].show() def exitEyeFSMOpen(self): pass def enterEyeFSMClosed(self): return None for lodName in self.getLODNames(): self.eyeLids[lodName].show() self.eyeBalls[lodName].hide() self.eyeIris[lodName].hide() def exitEyeFSMClosed(self): pass def getGlobalScale(self): return self.rootScale def calcBodyScale(self): idx = 0 if self.gender == "f": idx = 1 mappedValue = (0.80000000000000004 + (1 + self.style.getBodyHeight()) * 0.20000000000000001) * BodyScales[idx][ self.style.getBodyShape() ] return mappedValue def setupAnimDicts(cls): for t in BodyDefs.maleFrames: cls.storeAnimDict("models/char/mp", "m", t) for t in BodyDefs.femaleFrames: cls.storeAnimDict("models/char/fp", "f", t) setupAnimDicts = classmethod(setupAnimDicts) def storeAnimDict(cls, prefix, gender, type): qualifier = gender + type animList = AnimListDict[type] cls.prebuiltAnimData[qualifier] = {} for anim in animList: if anim[0] == "intro": continue animSuffix = "" for i in range(0, len(CustomAnimDict[qualifier])): if anim[0] == CustomAnimDict[qualifier][i]: animSuffix = "_" + gender + NewModelDict.get(type) break continue cls.prebuiltAnimData[qualifier][anim[0]] = prefix + "_" + anim[1] + animSuffix storeAnimDict = classmethod(storeAnimDict)
class Human(HumanBase.HumanBase, Biped.Biped): notify = DirectNotifyGlobal.directNotify.newCategory('Human') prebuiltAnimData = {} def __init__(self, other=None): Biped.Biped.__init__(self, other, HumanAnimationMixer) self.zombie = False self.crazyColorSkin = False self.crazyColorSkinIndex = 0 self.flattenPending = None self.flattenSuperLowName = None self.optimizeLOD = base.config.GetBool('optimize-avatar-lod', 1) self.loaded = 0 self.playingRate = None self.shadowFileName = 'models/misc/drop_shadow' self.setFont(PiratesGlobals.getInterfaceFont()) self._Human__blinkName = 'blink-' + str(self.this) self.eyeLids = None self.eyeBalls = None self.eyeIris = None self.reducedAnimList = None self.headNode = None self.headEffects = NodePath('headEffects') self.extraNode = None self.scaleNode = None self.rootNode = None self.floorOffsetZ = 0.0 self.isGhost = 0 self.headFudgeHpr = Vec3(0, 0, 0) self.randGen = random.Random() self.randGen.seed(random.random()) self.eyeFSM = ClassicFSM('eyeFSM', [ State('off', self.enterEyeFSMOff, self.exitEyeFSMOff, ['open', 'closed']), State('open', self.enterEyeFSMOpen, self.exitEyeFSMOpen, ['closed', 'off']), State('closed', self.enterEyeFSMClosed, self.exitEyeFSMClosed, ['open', 'off']) ], 'off', 'off') self.eyeFSM.enterInitialState() if other != None: self.copyHuman(other) def removeCopiedNodes(self): self.dropShadow = self.find('**/drop_shadow*') if not self.dropShadow.isEmpty(): self.deleteDropShadow() else: self.dropShadow = None billboardNode = self.find('**/billboardNode') if not billboardNode.isEmpty(): billboardNode.removeNode() self.getGeomNode().getParent().removeNode() def flattenHuman(self): self.getWeaponJoints() def flattenSuperLow(self): name = 'flattenSuperLow-%s' % self.this self.flattenSuperLowName = name model = self.getLOD('500') self.accept(name, self._Human__doneFlattenSuperLow) taskMgr.remove(name) taskMgr.add(self.flattenSuperLowTask, name, extraArgs=[model], taskChain='background') def flattenSuperLowTask(self, model): model = model.copyTo(NodePath()) rhn = model.find('**/rightHand') lhn = model.find('**/leftHand') if lhn: lhn.detachNode() if rhn: rhn.detachNode() node = model.node() gr = SceneGraphReducer() model.node().setAttrib(TransparencyAttrib.make(0), 2000) gr.applyAttribs( node, SceneGraphReducer.TTApplyTextureColor | SceneGraphReducer.TTTexMatrix | SceneGraphReducer.TTOther | SceneGraphReducer.TTCullFace | SceneGraphReducer.TTTransform | SceneGraphReducer.TTColor | SceneGraphReducer.TTColorScale) num_removed = gr.flatten(node, -1) gr.makeCompatibleState(node) gr.collectVertexData( node, ~(SceneGraphReducer.CVDFormat | SceneGraphReducer.CVDName | SceneGraphReducer.CVDAnimationType)) gr.unify(node, 0) name = self.flattenSuperLowName if name: messenger.send(name, [model], taskChain='default') def _Human__doneFlattenSuperLow(self, flat): self.headNode = flat.find('**/def_head01') self.rootNode = flat.find('**/dx_root') self.getWeaponJoints() orig = self.getLOD('500') orig.getChildren().detach() self.loadModel(flat, lodName='500', copy=False, autoBindAnims=False) self.getWeaponJoints() if hasattr(self, 'animProp') and self.animProp: self.resetAnimProp() self.findAllMatches('**/def_head01').detach() self.findAllMatches('**/dx_root').detach() for lodName in self.getLODNames(): if lodName == '500': self.headNode.reparentTo( self.getLOD(lodName).find('**/+Character')) self.rootNode.reparentTo( self.getLOD(lodName).find('**/+Character')) continue self.headNode.instanceTo( self.getLOD(lodName).find('**/+Character')) self.rootNode.instanceTo( self.getLOD(lodName).find('**/+Character')) self.headEffects.reparentTo(self.headNode) def _Human__doneFlattenHuman(self, models): self.flattenPending = None self.getWeaponJoints() def copyHuman(self, other): self.gender = other.gender self.loaded = other.loaded self.loadAnimatedHead = other.loadAnimatedHead self.rootScale = other.rootScale def delete(self): try: pass except: self.Human_deleted = 1 taskMgr.remove(self._Human__blinkName) name = self.flattenSuperLowName if name: self.flattenSuperLowName = None self.ignore(name) taskMgr.remove(name) if self.dropShadow and not self.dropShadow.isEmpty(): self.deleteDropShadow() del self.eyeFSM self.controlShapes = None self.sliderNames = None Biped.Biped.delete(self) def isDeleted(self): try: if self.Human_deleted == 1: return True except: return False def fixEyes(self): self.eyeLids = {} self.eyeBalls = {} self.eyeIris = {} for lodName in self.getLODNames(): geom = self.getPart('head', lodName) self.eyeLids[lodName] = geom.findAllMatches('**/*eyelid*') self.eyeBalls[lodName] = geom.findAllMatches('**/eye_ball*') self.eyeIris[lodName] = geom.findAllMatches('**/eye_iris*') self.eyeLids[lodName].stash() self.eyeBalls[lodName].unstash() self.eyeIris[lodName].unstash() def makeAnimDict(self, gender, animNames): self.animTable = [] for currAnim in animNames: anim = animNames.get(currAnim) for currAnimName in anim: self.animTable.append([currAnimName, currAnimName]) self.reducedAnimList = self.animTable def forceLoadAnimDict(self): for anim in self.animDict.keys(): self.getAnimControls(anim) def createAnimDict(self, customList=None): filePrefix = 'models/char/m' genderPrefix = 'm' if self.style.gender == 'f': self.type = BodyDefs.femaleFrames[self.style.getBodyShape()] filePrefix = 'models/char/f' genderPrefix = 'f' else: self.type = BodyDefs.maleFrames[self.style.getBodyShape()] if self.reducedAnimList is None: self.animDict = self.prebuiltAnimData[genderPrefix + self.type] return None filePrefix += 'p' animList = self.reducedAnimList self.animDict = {} for anim in animList: animSuffix = '' for i in range(0, len(CustomAnimDict[genderPrefix + self.type])): if anim[0] == CustomAnimDict[genderPrefix + self.type][i]: animSuffix = '_' + genderPrefix + NewModelDict.get( self.type) break continue self.animDict[anim[0]] = filePrefix + '_' + anim[1] + animSuffix return filePrefix def getIsPaid(self): return True def setupGhostNodes(self): lod = NodePath(self.getLODNode()) for node in lod.getChildren(): eyes = node.findAllMatches('**/eye*') if eyes: eyes.wrtReparentTo(eyes[0].getParent().attachNewNode( ModelNode('eyes'))) continue def loadHuman(self, other): other.style = self.style other.gender = self.style.gender other.model.dna = self.style self.createAnimDict() if self.style.gender == 'f': self.headFudgeHpr = Vec3(0, 0, 0) idx = 1 else: self.headFudgeHpr = Vec3(0, 0, 0) idx = 0 other.zombie = self.zombie other.crazyColorSkin = self.crazyColorSkin other.setCrazyColorSkinIndex(self.getCrazyColorSkinIndex()) yieldThread('anim dict') other.isPaid = self.getIsPaid() other.showLOD(2000) yieldThread('showLOD') base.loadingScreen.tick() if other.zombie: other.showZombie() if hasattr(self, 'motionFSM'): self.motionFSM.setAvatar(self) base.loadingScreen.tick() yieldThread('zombie') other.applyBodyShaper() base.loadingScreen.tick() yieldThread('body shaper') base.loadingScreen.tick() other.applyHeadShaper() yieldThread('head shaper') base.loadingScreen.tick() if self.zombie == 2: other.model.eyeBalls.unstash() other.model.irises.stash() elif self.zombie: other.model.eyeBalls.stash() other.model.irises.stash() else: other.model.eyeBalls.unstash() other.model.irises.unstash() base.loadingScreen.tick() self.copyActor(other) base.loadingScreen.tick() self.floorOffsetZ = other.rootNode.getZ() yieldThread('copyActor') self.copyHuman(other) if self.isGhost: self.setupGhostNodes() gnodes = self.getLOD('500').findAllMatches('**/+GeomNode') for node in gnodes: node.setTextureOff(other.model.tattooStage) base.loadingScreen.tick() self.flattenSuperLow() self.rootNode = self.getLOD('500').find('**/dx_root') self.headNode = self.getLOD('500').find('**/def_head01') lodNames = self.getLODNames() self.scaleNode = self.controlJoint(None, 'legs', 'def_scale_jt', lodNames[0]) if len(lodNames) > 1: for i in range(1, len(lodNames)): self.controlJoint(self.scaleNode, 'legs', 'def_scale_jt', lodNames[i]) self.setGlobalScale(self.calcBodyScale()) yieldThread('copyHuman') base.loadingScreen.tick() self.loadAnimsOnAllLODs(self.animDict, 'modelRoot') base.loadingScreen.tick() yieldThread('loadAnims') other.zombie = 0 other.crazyColorSkin = 0 other.setCrazyColorSkinIndex(0) other.showNormal() yieldThread('show normal') self.initializeNametag3d() self.initializeDropShadow() self.setName(self.getName()) yieldThread('misc nodes') base.loadingScreen.tick() self.loaded = 1 def setGlobalScale(self, scale): self.scaleNode.setScale(scale) self.rootScale = scale self.scaleNode.setZ(-(self.floorOffsetZ * (1 - scale))) def initializeMiscNodes(self): self.initializeNametag3d() self.initializeDropShadow() def undoControlJoints(self): self.getGeomNode().getParent().findAllMatches('def_*').detach() self.getGeomNode().getParent().findAllMatches('trs_*').detach() self.findAllMatches('def_*').detach() self.findAllMatches('trs_*').detach() def cleanupHuman(self, gender='m'): self.eyeFSM.request('off') self.undoControlJoints() self.removeCopiedNodes() self.eyeLids = {} self.eyeBalls = {} self.eyeIris = {} self.flush() self.loaded = 0 self.master = 0 def getCrazyColorSkinIndex(self): return self.crazyColorSkinIndex def setCrazyColorSkinIndex(self, index): if len(HumanDNA.crazySkinColors) > index: self.crazyColorSkinIndex = index else: self.notify.warning( '(Human)index: %d is out of bounds for crazyColorSkin: %d' % (index, len(HumanDNA.crazySkinColors))) def generateHuman(self, gender, others, useFaceTex=False): parent = self.getParent() self.detachNode() if gender == 'f': other = others[1] else: other = others[0] if self.loaded: self.cleanupHuman() other.useFaceTex = useFaceTex self.loadHuman(other) if self.isLocal(): self.renderReflection = True self.setRenderReflection() self.resetEffectParent() self.enableMixing() self.reparentTo(parent) def getShadowJoint(self): return self.nametagNodePath def getNametagJoints(self): joints = [] for lodName in self.getLODNames(): bundle = self.getPartBundle('modelRoot', lodName) joint = bundle.findChild('name_tag') if joint: joints.append(joint) continue return joints def _Human__blinkOpenEyes(self, task): if self.eyeFSM.getCurrentState().getName() == 'closed': self.eyeFSM.request('open') r = self.randGen.random() if r < 0.10000000000000001: t = 0.20000000000000001 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self._Human__blinkCloseEyes, self._Human__blinkName) return Task.done def _Human__blinkCloseEyes(self, task): if self.eyeFSM.getCurrentState().getName() != 'open': taskMgr.doMethodLater(4.0, self._Human__blinkCloseEyes, self._Human__blinkName) else: self.eyeFSM.request('closed') taskMgr.doMethodLater(0.125, self._Human__blinkOpenEyes, self._Human__blinkName) return Task.done def startBlink(self): taskMgr.remove(self._Human__blinkName) if self.eyeLids: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self._Human__blinkCloseEyes, self._Human__blinkName) def stopBlink(self): taskMgr.remove(self._Human__blinkName) if self.eyeLids: self.eyeFSM.request('open') def closeEyes(self): self.eyeFSM.request('closed') def openEyes(self): self.eyeFSM.request('open') def enterEyeFSMOff(self): pass def exitEyeFSMOff(self): pass def enterEyeFSMOpen(self): for lodName in self.getLODNames(): self.eyeLids[lodName].hide() self.eyeBalls[lodName].show() self.eyeIris[lodName].show() def exitEyeFSMOpen(self): pass def enterEyeFSMClosed(self): return None for lodName in self.getLODNames(): self.eyeLids[lodName].show() self.eyeBalls[lodName].hide() self.eyeIris[lodName].hide() def exitEyeFSMClosed(self): pass def getGlobalScale(self): return self.rootScale def calcBodyScale(self): idx = 0 if self.gender == 'f': idx = 1 mappedValue = (0.80000000000000004 + (1 + self.style.getBodyHeight()) * 0.20000000000000001 ) * BodyScales[idx][self.style.getBodyShape()] return mappedValue def setupAnimDicts(cls): for t in BodyDefs.maleFrames: cls.storeAnimDict('models/char/mp', 'm', t) for t in BodyDefs.femaleFrames: cls.storeAnimDict('models/char/fp', 'f', t) setupAnimDicts = classmethod(setupAnimDicts) def storeAnimDict(cls, prefix, gender, type): qualifier = gender + type animList = AnimListDict[type] cls.prebuiltAnimData[qualifier] = {} for anim in animList: if anim[0] == 'intro': continue animSuffix = '' for i in range(0, len(CustomAnimDict[qualifier])): if anim[0] == CustomAnimDict[qualifier][i]: animSuffix = '_' + gender + NewModelDict.get(type) break continue cls.prebuiltAnimData[qualifier][ anim[0]] = prefix + '_' + anim[1] + animSuffix storeAnimDict = classmethod(storeAnimDict)
class CogInvasionClientRepository(AstronClientRepository): notify = directNotify.newCategory("CIClientRepository") GameGlobalsId = DO_ID_COGINVASION SetZoneDoneEvent = 'CICRSetZoneDone' EmuSetZoneDoneEvent = 'CICREmuSetZoneDone' SetInterest = 'Set' ClearInterest = 'Clear' ClearInterestDoneEvent = 'CICRClearInterestDone' ITAG_PERM = 'perm' ITAG_AVATAR = 'avatar' ITAG_SHARD = 'shard' ITAG_WORLD = 'world' ITAG_GAME = 'game' def __init__(self, serverVersion): self.serverVersion = serverVersion AstronClientRepository.__init__( self, ['phase_3/etc/direct.dc', 'phase_3/etc/toon.dc']) self.loginFSM = ClassicFSM('login', [ State('off', self.enterOff, self.exitOff), State('connect', self.enterConnect, self.exitConnect), State('disconnect', self.enterDisconnect, self.exitDisconnect), State('avChoose', self.enterAvChoose, self.exitAvChoose), State('playingGame', self.enterPlayingGame, self.exitPlayingGame), State('serverUnavailable', self.enterServerUnavailable, self.exitServerUnavailable), State('makeAToon', self.enterMakeAToon, self.exitMakeAToon), State('submitNewToon', self.enterSubmitNewToon, self.exitSubmitNewToon), State('noShards', self.enterNoShards, self.exitNoShards), State('waitForSetAvatarResponse', self.enterWaitForSetAvatarResponse, self.exitWaitForSetAvatarResponse), State('waitForShardList', self.enterWaitForShardList, self.exitWaitForShardList), State('ejected', self.enterEjected, self.exitEjected), State('districtReset', self.enterDistrictReset, self.exitDistrictReset), State('died', self.enterDied, self.exitDied), State('betaInform', self.enterBetaInform, self.exitBetaInform) ], 'off', 'off') self.loginFSM.enterInitialState() self.gameFSM = ClassicFSM('game', [ State('off', self.enterGameOff, self.exitGameOff), State('waitForGameEnterResponse', self.enterWaitForGameEnterResponse, self.exitWaitForGameEnterResponse), State('playGame', self.enterPlayGame, self.exitPlayGame), State('closeShard', self.enterCloseShard, self.exitCloseShard), State('switchShards', self.enterSwitchShards, self.exitSwitchShards) ], 'off', 'off') self.gameFSM.enterInitialState() #self.taskNameAllocator = UniqueIdAllocator(0, 1000000000) self.avChooser = AvChooser(self.loginFSM) self.playGame = PlayGame(self.gameFSM, "playGameDone") self.hoodMgr = HoodMgr() self.makeAToon = MakeAToon() self.loginToken = os.environ.get("LOGIN_TOKEN") self.serverAddress = os.environ.get("GAME_SERVER") self.serverURL = URLSpec("http://%s" % self.serverAddress) self.parentMgr.registerParent(CIGlobals.SPRender, render) self.parentMgr.registerParent(CIGlobals.SPHidden, hidden) self.adminAccess = False self.localAvChoice = None self.SuitsActive = 0 self.BossActive = 0 self.accServerTimesNA = 0 self.maxAccServerTimesNA = 10 self.setZonesEmulated = 0 self.old_setzone_interest_handle = None self.setZoneQueue = Queue() self.accept(self.SetZoneDoneEvent, self._handleEmuSetZoneDone) self.handler = None self.__currentAvId = 0 self.myDistrict = None self.activeDistricts = {} self.shardListHandle = None self.uberZoneInterest = None self.isShowingPlayerIds = False self.doBetaInform = False self.dTutorial = None self.requestedName = None self.whisperNoise = base.loadSfx( 'phase_3.5/audio/sfx/GUI_whisper_3.ogg') self.checkHttp() #self.http.addPreapprovedServerCertificateFilename(self.serverURL, Filename('phase_3/etc/gameserver.crt')) #self.tournamentMusicChunks = {} #self.threadedTaskChain = taskMgr.setupTaskChain("threadedTaskChainForSoundIntervals", numThreads = 2) self.attackMgr = base.cl_attackMgr base.minigame = None self.newToonSlot = None base.finalExitCallbacks.insert(0, self.__handleExit) self.accountName = os.environ.get('ACCOUNT_NAME', '') self.csm = self.generateGlobalObject(DO_ID_CLIENT_SERVICES_MANAGER, 'ClientServicesManager') self.friendsManager = self.generateGlobalObject( DO_ID_FRIENDS_MANAGER, 'FriendsManager') self.uin = self.generateGlobalObject(DO_ID_UNIQUE_INTEREST_NOTIFIER, 'UniqueInterestNotifier') self.statsManager = self.generateGlobalObject(DO_ID_STATS_MANAGER, 'StatsManager') self.pingToggle = False self.currentPing = None self.pingText = OnscreenText("", align=TextNode.ALeft, parent=base.a2dBottomLeft, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 0.5), pos=(0.3, 0.09)) self.pingText.setBin('gsg-popup', 1000) self.pingText.hide() SpeedHackChecker.startChecking() self.loginFSM.request('connect') return def readerPollUntilEmpty(self, task): while self.readerPollOnce(): pass if not metadata.IS_PRODUCTION: if ConfigVariableBool('simulated-latency', False).getValue(): latency = random.uniform( ConfigVariableDouble('simulated-latency-min', 0.125).getValue(), ConfigVariableDouble('simulated-latency-max', 0.15).getValue()) task.delayTime = latency return task.again return task.cont def togglePing(self): self.pingToggle = not self.pingToggle if self.pingToggle: taskMgr.add(self.__districtPingTask, "CICR.districtPingTask") self.showPing() else: self.hidePing() taskMgr.remove("CICR.districtPingTask") def showPing(self): self.pingText.show() def hidePing(self): self.pingText.hide() def handleNewPing(self): if self.currentPing is None: display = "?" else: display = int(round(self.currentPing)) self.pingText.setText("Ping: {0} ms".format(display)) def __districtPingTask(self, task): if self.myDistrict: # Figure out how much network latency there is. self.myDistrict.d_ping() task.delayTime = 1.0 return task.again def deleteObject(self, doId): """ implementation copied from AstronClientRepository.py Brian: modified to also delete owner views Removes the object from the client's view of the world. This should normally not be called directly except in the case of error recovery, since the server will normally be responsible for deleting and disabling objects as they go out of scope. After this is called, future updates by server on this object will be ignored (with a warning message). The object will become valid again the next time the server sends a generate message for this doId. This is not a distributed message and does not delete the object on the server or on any other client. """ if doId in self.doId2do: # If it is in the dictionary, remove it. obj = self.doId2do[doId] # Remove it from the dictionary del self.doId2do[doId] # Disable, announce, and delete the object itself... # unless delayDelete is on... obj.deleteOrDelay() if self.isLocalId(doId): self.freeDoId(doId) elif doId in self.doId2ownerView: # If it is in the owner dictionary, remove it. obj = self.doId2ownerView[doId] # Remove it from the dictionary del self.doId2ownerView[doId] # Disable, announce, and delete the object itself... # unless delayDelete is on... obj.deleteOrDelay() if self.isLocalId(doId): self.freeDoId(doId) elif self.cache.contains(doId): # If it is in the cache, remove it. self.cache.delete(doId) if self.isLocalId(doId): self.freeDoId(doId) elif self.cacheOwner.contains(doId): # If it is in the owner cache, remove it. self.cacheOwner.delete(doId) if self.isLocalId(doId): self.freeDoId(doId) else: # Otherwise, ignore it self.notify.warning("Asked to delete non-existent DistObj " + str(doId)) #def uniqueName(self, idString): # return "%s-%s" % (idString, self.taskNameAllocator.allocate()) #def removeTask(self, taskName): # div = taskName.split('-') # self.taskNameAllocator.free(div[1]) # taskMgr.remove(taskName) def __handleExit(self): try: base.localAvatar.b_setAnimState('teleportOut') except: pass ccoginvasion.CTMusicData.stop_am_update_task() self.gameFSM.request('closeShard', ['off']) def isChristmas(self): return self.holidayManager.getHoliday() == HolidayType.CHRISTMAS def showPlayerIds(self): print "Showing player ids..." self.isShowingPlayerIds = True for av in self.doId2do.values(): if av.__class__.__name__ in [ "DistributedPlayerToon", "LocalToon", "DistributedSuit" ]: av.showAvId() def hidePlayerIds(self): print "Hiding player ids..." self.isShowingPlayerIds = False for av in self.doId2do.values(): if av.__class__.__name__ in [ "DistributedPlayerToon", "LocalToon", 'DistributedSuit' ]: av.showName() def sendSetLocation(self, doId, parentId, zoneId): dg = PyDatagram() dg.addUint16(CLIENT_OBJECT_LOCATION) dg.addUint32(doId) dg.addUint32(parentId) dg.addUint32(zoneId) self.send(dg) def getNextSetZoneDoneEvent(self): return '%s-%s' % (self.EmuSetZoneDoneEvent, self.setZonesEmulated + 1) def getLastSetZoneDoneEvent(self): return '%s-%s' % (self.EmuSetZoneDoneEvent, self.setZonesEmulated) def getQuietZoneLeftEvent(self): return 'leftQuietZone-%s' % (id(self), ) def b_setLocation(self, do, parentId, zoneId): self.sendSetLocation(do.doId, parentId, zoneId) do.setLocation(parentId, zoneId) def sendSetZoneMsg(self, zoneId, visibleZoneList=None): event = self.getNextSetZoneDoneEvent() self.setZonesEmulated += 1 parentId = base.localAvatar.defaultShard self.sendSetLocation(base.localAvatar.doId, parentId, zoneId) localAvatar.setLocation(parentId, zoneId) interestZones = zoneId if visibleZoneList is not None: interestZones = visibleZoneList self._addInterestOpToQueue( self.SetInterest, [parentId, interestZones, 'OldSetZoneEmulator'], event) return def resetInterestStateForConnectionLoss(self): self.old_setzone_interest_handle = None self.setZoneQueue.clear() return def _removeEmulatedSetZone(self, doneEvent): self._addInterestOpToQueue(self.ClearInterest, None, doneEvent) return def _addInterestOpToQueue(self, op, args, event): self.setZoneQueue.push([op, args, event]) if len(self.setZoneQueue) == 1: self._sendNextSetZone() def _sendNextSetZone(self): op, args, event = self.setZoneQueue.top() if op == self.SetInterest: parentId, interestZones, name = args if self.old_setzone_interest_handle is None: self.old_setzone_interest_handle = self.addInterest( parentId, interestZones, name, self.SetZoneDoneEvent) else: self.alterInterest(self.old_setzone_interest_handle, parentId, interestZones, name, self.SetZoneDoneEvent) elif op == self.ClearInterest: self.removeInterest(self.old_setzone_interest_handle, self.SetZoneDoneEvent) self.old_setzone_interest_handle = None else: self.notify.error('unknown setZone op: %s' % op) return def _handleEmuSetZoneDone(self): op, args, event = self.setZoneQueue.pop() queueIsEmpty = self.setZoneQueue.isEmpty() if event is not None: messenger.send(event) if not queueIsEmpty: self._sendNextSetZone() return def enterSwitchShards(self, shardId, hoodId, zoneId, avId): self._switchShardParams = [shardId, hoodId, zoneId, avId] self.removeShardInterest(self._handleOldShardGone) def _handleOldShardGone(self): status = {} status['hoodId'] = self._switchShardParams[1] status['zoneId'] = self._switchShardParams[2] status['avId'] = self._switchShardParams[3] self.gameFSM.request('waitForGameEnterResponse', [status, self._switchShardParams[0]]) def exitSwitchShards(self): del self._switchShardParams def enterBetaInform(self): msg = ( "Welcome to Cog Invasion Online!\n\nBefore playing, please remember that the game is in Alpha, " "and that you may encounter bugs and incomplete features.\n\nIf you happen to encounter any bugs, " "please report them to us by using the Contact Us Page at coginvasion.com.\n\nHave fun!" ) self.dialog = GlobalDialog(message=msg, style=3, doneEvent="gameEnterChoice") self.dialog.show() self.acceptOnce("gameEnterChoice", self.handleGameEnterChoice) def handleGameEnterChoice(self): self.loginFSM.request('avChoose') def exitBetaInform(self): self.ignore("gameEnterChoice") self.dialog.cleanup() del self.dialog def enterCloseShard(self, nextState='avChoose'): self.setNoNewInterests(True) self._removeLocalAvFromStateServer(nextState) def exitCloseShard(self): self.setNoNewInterests(False) self.ignore(self.ClearInterestDoneEvent) return def _removeLocalAvFromStateServer(self, nextState): self.sendSetAvatarIdMsg(0) self._removeAllOV() callback = Functor(self.loginFSM.request, nextState) self.removeShardInterest(callback) def removeShardInterest(self, callback): self._removeCurrentShardInterest( Functor(self._removeShardInterestComplete, callback)) def _removeShardInterestComplete(self, callback): self.cache.flush() self.doDataCache.flush() callback() return def _removeCurrentShardInterest(self, callback): if self.old_setzone_interest_handle is None: callback() return self.acceptOnce(self.ClearInterestDoneEvent, Functor(self._removeCurrentUberZoneInterest, callback)) self._removeEmulatedSetZone(self.ClearInterestDoneEvent) return def _removeCurrentUberZoneInterest(self, callback): self.acceptOnce(self.ClearInterestDoneEvent, Functor(self._removeShardInterestDone, callback)) self.removeInterest(self.uberZoneInterest, self.ClearInterestDoneEvent) def _removeShardInterestDone(self, callback): self.uberZoneInterest = None callback() return def _removeAllOV(self): owners = self.doId2ownerView.keys() for doId in owners: self.disableDoId(doId, ownerView=True) def enterDied(self): self.deathDialog = GlobalDialog(message=CIGlobals.SuitDefeatMsg, style=2, doneEvent="deathChoice") self.deathDialog.show() self.acceptOnce("deathChoice", self.handleDeathChoice) def handleDeathChoice(self): value = self.deathDialog.getValue() if value: self.loginFSM.request('avChoose') else: sys.exit() def exitDied(self): self.deathDialog.cleanup() del self.deathDialog self.ignore("deathChoice") def enterConnect(self): self.connectingDialog = GlobalDialog(message=CIGlobals.ConnectingMsg) self.connectingDialog.show() self.connect([self.serverURL], successCallback=self.handleConnected, failureCallback=self.handleConnectFail) def handleConnected(self): self.notify.info("Sending CLIENT_HELLO...") self.acceptOnce("CLIENT_HELLO_RESP", self.handleClientHelloResp) self.acceptOnce("CLIENT_EJECT", self.handleEjected) self.acceptOnce("LOST_CONNECTION", self.handleLostConnection) AstronClientRepository.sendHello(self, self.serverVersion) def handleLostConnection(self): self.deleteAllObjects() self.loginFSM.request('disconnect', [1]) def deleteAllObjects(self): for doId in self.doId2do.keys(): obj = self.doId2do[doId] if not isinstance(obj, DistributedObjectGlobal) and not hasattr( obj, 'isDistrict'): if hasattr(base, 'localAvatar') and doId != base.localAvatar.doId: self.deleteObject(doId) def handleEjected(self, errorCode, reason): self.notify.info("OMG I WAS EJECTED!") self.ignore("LOST_CONNECTION") errorMsg = ErrorCode2ErrorMsg.get(errorCode, None) or UnknownErrorMsg % errorCode self.loginFSM.request('ejected', [errorMsg]) def handleClientHelloResp(self): self.notify.info("Got CLIENT_HELLO_RESP!") self.acceptOnce(self.csm.getLoginAcceptedEvent(), self.handleLoginAccepted) self.csm.d_requestLogin(self.loginToken, self.accountName) def handleLoginAccepted(self): self.notify.info("Woo-hoo, I am authenticated!") base.cr.holidayManager = self.generateGlobalObject( DO_ID_HOLIDAY_MANAGER, 'HolidayManager') base.cr.nameServicesManager = self.generateGlobalObject( DO_ID_NAME_SERVICES_MANAGER, 'NameServicesManager') self.loginFSM.request('waitForShardList') def handleConnectFail(self, _, __): self.notify.info("Could not connect to gameserver, notifying user.") self.connectingDialog.cleanup() self.connectingDialog = GlobalDialog( message=CIGlobals.NoConnectionMsg % self.serverAddress + " " + CIGlobals.TryAgain, style=2, doneEvent="connectFail") self.connectingDialog.show() self.acceptOnce("connectFail", self.handleConnectFailButton) def handleConnectFailButton(self): value = self.connectingDialog.getValue() if value: self.loginFSM.request('connect') else: sys.exit() def exitConnect(self): self.ignore("connectFail") self.ignore("CLIENT_HELLO_RESP") self.ignore(self.csm.getLoginAcceptedEvent()) self.connectingDialog.cleanup() del self.connectingDialog def enterEjected(self, errorMsg): self.ejectDialog = GlobalDialog(message=errorMsg, style=3, doneEvent='ejectDone') self.ejectDialog.show() self.acceptOnce('ejectDone', sys.exit) def exitEjected(self): self.ignore('ejectDone') self.ejectDialog.cleanup() del self.ejectDialog def enterServerUnavailable(self): self.notify.info(CIGlobals.ServerUnavailable) self.serverNA = GlobalDialog(message=CIGlobals.ServerUnavailable, style=4, doneEvent="serverNAEvent") self.serverNA.show() self.acceptOnce("serverNAEvent", sys.exit) self.startServerNAPoll() def startServerNAPoll(self): self.notify.info("Starting server poll...") self.accServerTimesNA = 1 taskMgr.add(self.serverNAPoll, "serverNAPoll") def serverNAPoll(self, task): dg = PyDatagram() dg.addUint16(ACC_IS_SERVER_UP) self.send(dg) task.delayTime = 3.0 return Task.again def __handleServerNAResp(self, resp): if resp == ACC_SERVER_UP: taskMgr.remove("serverNAPoll") # Enter the previous state that we were in, which should have # been some state where we communicate with the acc server. self.loginFSM.request(self.loginFSM.getLastState().getName()) else: self.accServerTimesNA += 1 if self.accServerTimesNA >= self.maxAccServerTimesNA: taskMgr.remove("serverNAPoll") self.notify.info( "Giving up on polling account server after %s times." % self.accServerTimesNA) self.loginFSM.request("disconnect", enterArgList=[1]) self.accServerTimesNA = 0 def exitServerUnavailable(self): self.ignore("serverNAEvent") self.serverNA.cleanup() del self.serverNA def enterOff(self): pass def exitOff(self): pass def playTheme(self): base.playMusic(CIGlobals.getThemeSong(), looping=1) def enterAvChoose(self, newToonSlot=None): ModelPool.garbageCollect() TexturePool.garbageCollect() self.avChooser.load() self.avChooser.enter(newToonSlot) if newToonSlot is None: self.playTheme() self.accept("enterMakeAToon", self.__handleMakeAToonReq) self.accept("avChooseDone", self.__handleAvChooseDone) def __handleMakeAToonReq(self, slot): self.loginFSM.request('makeAToon', [slot]) def __handleAvChooseDone(self, avChoice): print "------- AvChooseDone -------" print "Toon name: %s" % avChoice.getName() print "Slot: %s" % avChoice.getSlot() print "DNA: %s" % avChoice.getDNA() self.loginFSM.request("waitForSetAvatarResponse", [avChoice]) def exitAvChoose(self): self.avChooser.exit() self.avChooser.unload() self.ignore("enterMakeAToon") self.ignore("avChooseDone") def handlePlayGame(self, msgType, di): if msgType == CLIENT_ENTER_OBJECT_REQUIRED_OTHER_OWNER: self.handleGenerateWithRequiredOtherOwner(msgType, di) else: AstronClientRepository.handleDatagram(self, di) def enterPlayingGame(self): zoneId = localAvatar.getLastHood() hoodId = ZoneUtil.getHoodId(zoneId) status = {"hoodId": hoodId, "zoneId": zoneId, "avId": self.localAvId} shardId = self.myDistrict.doId self.gameFSM.request('waitForGameEnterResponse', [status, shardId]) def exitPlayingGame(self): self.deleteAllObjects() self.handler = None self.gameFSM.request('off') camera.reparentTo(render) camera.setPos(0, 0, 0) camera.setHpr(0, 0, 0) self.localAvChoice = None if loader.inBulkBlock: loader.endBulkLoad(loader.blockName) def enterNoShards(self): self.noShardDialog = GlobalDialog(message=CIGlobals.NoShardsMsg + " " + CIGlobals.TryAgain, style=2, doneEvent='noShardsDone') self.noShardDialog.show() self.acceptOnce('noShardsDone', self.handleNoShardsDone) def handleNoShardsDone(self): value = self.noShardDialog.getValue() if value: self.loginFSM.request('waitForShardList') else: sys.exit() def exitNoShards(self): self.noShardDialog.cleanup() del self.noShardDialog self.ignore('noShardsDone') def enterWaitForShardList(self): self.shardListHandle = self.addTaggedInterest( self.GameGlobalsId, ZoneUtil.DistrictZone, self.ITAG_PERM, 'localShardList', event='shardList_complete') self.acceptOnce('shardList_complete', self._handleShardListComplete) def _handleShardListComplete(self): if self._shardsAreAvailable(): self.myDistrict = self._chooseAShard() if self.doBetaInform: self.loginFSM.request('betaInform') else: self.loginFSM.request('avChoose') taskMgr.add(self.monitorDistrict, "monitorMyDistrict") else: self.loginFSM.request('noShards') def monitorDistrict(self, task): if self.myDistrict is None and self.isConnected(): self.loginFSM.request('districtReset') return task.done return task.cont def _shardsAreAvailable(self): for shard in self.activeDistricts.values(): if shard.available: return True return False def _chooseAShard(self): choices = [] for shard in self.activeDistricts.values(): choices.append(shard) return random.choice(choices) def exitWaitForShardList(self): self.ignore('shardList_complete') def enterDistrictReset(self): self.districtResetDialog = GlobalDialog( message=CIGlobals.DistrictResetMsg, style=3, doneEvent='distresetdone') self.districtResetDialog.show() self.acceptOnce('distresetdone', sys.exit) def exitDistrictReset(self): self.districtResetDialog.cleanup() del self.districtResetDialog def enterWaitForSetAvatarResponse(self, choice): #self.acceptOnce(self.csm.getSetAvatarEvent(), self.__handleSetAvatarResponse) self.sendSetAvatarMsg(choice) def enterLoadDone(self): self.loginFSM.request("playingGame") def __handleSetAvatarResponse(self, avId, di): print "Entering game..." enterLoad = EnterLoad(self.enterLoadDone) dclass = self.dclassesByName['DistributedPlayerToon'] localAvatar = LocalToon.LocalToon(base.cr) localAvatar.dclass = dclass base.localAvatar = localAvatar __builtins__['localAvatar'] = base.localAvatar localAvatar.doId = avId self.localAvId = avId parentId = None zoneId = None localAvatar.setLocation(parentId, zoneId) localAvatar.generateInit() localAvatar.generate() dclass.receiveUpdateBroadcastRequiredOwner(localAvatar, di) localAvatar.announceGenerate() localAvatar.postGenerateMessage() self.doId2do[avId] = localAvatar # TEMPORARY: #localAvatar.hoodsDiscovered = [1000, 2000, 3000, 4000, 5000, 9000] #localAvatar.teleportAccess = [1000, 2000, 3000, 4000, 5000, 9000] enterLoad.load() del enterLoad def exitWaitForSetAvatarResponse(self): self.ignore(self.csm.getSetAvatarEvent()) def enterWaitForGameEnterResponse(self, status, shardId): if shardId is not None: district = self.activeDistricts[shardId] else: district = None if not district: self.loginFSM.request('noShards') return else: self.myDistrict = district self.notify.info("Entering shard %s" % shardId) localAvatar.setLocation(shardId, status['zoneId']) localAvatar.defaultShard = shardId self.handleEnteredShard(status) return def handleEnteredShard(self, status): self.uberZoneInterest = self.addInterest(localAvatar.defaultShard, ZoneUtil.UberZone, 'uberZone', 'uberZoneInterestComplete') self.acceptOnce('uberZoneInterestComplete', self.uberZoneInterestComplete, [status]) def uberZoneInterestComplete(self, status): self.__gotTimeSync = 0 if self.timeManager is None: print "No time manager" DistributedSmoothNode.globalActivateSmoothing(0, 0) self.gotTimeSync(status) else: print "Time manager found" DistributedSmoothNode.globalActivateSmoothing(1, 0) #h = HashVal() #hashPrcVariables(h) #pyc = HashVal() #if not __dev__: # self.hashFiles(pyc) #self.timeManager.d_setSignature(self.userSignature, h.asBin(), pyc.asBin()) #self.timeManager.sendCpuInfo() self.timeManager.lastAttempt = -self.timeManager.minWait * 2 if self.timeManager.synchronize('startup'): self.accept('gotTimeSync', self.gotTimeSync, [status]) else: self.gotTimeSync(status) return def getPing(self): if self.myDistrict: return self.myDistrict.currentPing return 0 def exitWaitForGameEnterResponse(self): self.ignore('uberZoneInterestComplete') return def gotTimeSync(self, status): self.notify.info('gotTimeSync') self.ignore('gotTimeSync') self.__gotTimeSync = 1 self.prepareToEnter(status) def prepareToEnter(self, status): if not self.__gotTimeSync: self.notify.info("still waiting for time sync") return self.gameFSM.request('playGame', [status]) def enterMakeAToon(self, slot): base.stopMusic() self.makeAToon.setSlot(slot) self.makeAToon.loadEnviron() self.makeAToon.load() self.makeAToon.matFSM.request('genderShop') self.acceptOnce("quitCreateAToon", self.__handleMakeAToonQuit) self.acceptOnce("createAToonFinished", self.__handleMakeAToonDone) def __handleMakeAToonQuit(self): self.loginFSM.request("avChoose") def __handleMakeAToonDone(self, dnaStrand, slot, name): self.loginFSM.request('submitNewToon', enterArgList=[dnaStrand, slot, name]) def exitMakeAToon(self): self.makeAToon.setSlot(-1) self.makeAToon.enterExit(None) self.ignore("quitCreateAToon") self.ignore("createAToonFinished") def enterSubmitNewToon(self, dnaStrand, slot, name, skipTutorial=0): self.newToonSlot = slot self.submittingDialog = GlobalDialog(message=CIGlobals.Submitting) self.submittingDialog.show() self.acceptOnce(self.csm.getToonCreatedEvent(), self.__handleSubmitNewToonResp) self.csm.sendSubmitNewToon(dnaStrand, slot, name, skipTutorial) def __handleSubmitNewToonResp(self, avId): # Now that our toon exists in the database, we can add send over the name we wanted to NameServicesManagerUD. if self.requestedName is not None: self.nameServicesManager.d_requestName(self.requestedName, avId) self.requestedName = None self.loginFSM.request('avChoose', [self.newToonSlot]) def exitSubmitNewToon(self): self.newToonSlot = None self.ignore(self.csm.getToonCreatedEvent()) self.submittingDialog.cleanup() del self.submittingDialog def enterGameOff(self): pass def exitGameOff(self): pass def enterPlayGame(self, status): base.stopMusic() base.transitions.noFade() if self.localAvChoice is None: self.notify.error( "called enterPlayGame() without self.localAvChoice being set!") return if localAvatar.getTutorialCompleted() == 1: zoneId = status['zoneId'] hoodId = status['hoodId'] avId = status['avId'] self.playGame.load() self.playGame.enter(hoodId, zoneId, avId) else: self.sendQuietZoneRequest() localAvatar.sendUpdate('createTutorial') self.myDistrict.d_joining() def tutorialCreated(self, zoneId): # zoneId = the zone the tutorial resides in # tutId = the doId of the tutorial requestStatus = {'zoneId': zoneId} self.tutQuietZoneState = QuietZoneState('tutQuietZoneDone') self.tutQuietZoneState.load() self.tutQuietZoneState.enter(requestStatus) self.acceptOnce('tutQuietZoneDone', self.__handleTutQuietZoneDone) def __handleTutQuietZoneDone(self): # We've entered the zone that the tutorial is in. self.tutQuietZoneState.exit() self.tutQuietZoneState.unload() del self.tutQuietZoneState def exitPlayGame(self): self.ignore('tutQuietZoneDone') if hasattr(self, 'tutQuietZoneDone'): self.tutQuietZoneState.exit() self.tutQuietZoneState.unload() del self.tutQuietZoneState base.stopMusic() self.playGame.exit() self.playGame.unload() def enterDisconnect(self, isPlaying, booted=0, bootReason=None): self.notify.info( "Disconnect details: isPlaying = %s, booted = %s, bootReason = %s" % (isPlaying, booted, bootReason)) style = 3 if isPlaying == 1: if not booted: msg = CIGlobals.DisconnectionMsg else: if not booted: msg = CIGlobals.JoinFailureMsg if self.isConnected(): self.sendDisconnect() self.disconnectDialog = GlobalDialog(message=msg, style=style, doneEvent="disconnectDone") self.disconnectDialog.show() if style == 3: self.acceptOnce("disconnectDone", sys.exit) else: self.acceptOnce("disconnectDone", self.handleDisconnectDone) def handleDisconnectDone(self): value = self.disconnectDialog.getValue() if value: self.loginFSM.request('connect') else: sys.exit() def exitDisconnect(self): self.ignore("disconnectDone") self.disconnectDialog.cleanup() del self.disconnectDialog def renderFrame(self): gsg = base.win.getGsg() if gsg: render2d.prepareScene(gsg) base.graphicsEngine.renderFrame() def renderFrames(self): base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() def handleDatagram(self, di): if self.notify.getDebug(): print "ClientRepository received datagram:" #di.getDatagram().dumpHex(ostream) msgType = self.getMsgType() self.currentSenderId = None if self.handler is None: self.astronHandle(di) else: self.handler(msgType, di) self.considerHeartbeat() def astronHandle(self, di): AstronClientRepository.handleDatagram(self, di) def handleQuietZoneGenerateWithRequired(self, di): doId = di.getUint32() parentId = di.getUint32() zoneId = di.getUint32() classId = di.getUint16() dclass = self.dclassesByNumber[classId] if dclass.getClassDef().neverDisable: dclass.startGenerate() distObj = self.generateWithRequiredFields(dclass, doId, di, parentId, zoneId) dclass.stopGenerate() def handleQuietZoneGenerateWithRequiredOther(self, di): doId = di.getUint32() parentId = di.getUint32() zoneId = di.getUint32() classId = di.getUint16() dclass = self.dclassesByNumber[classId] if dclass.getClassDef().neverDisable: dclass.startGenerate() distObj = self.generateWithRequiredOtherFields( dclass, doId, di, parentId, zoneId) dclass.stopGenerate() def handleQuietZoneUpdateField(self, di): di2 = DatagramIterator(di) doId = di2.getUint32() if doId in self.deferredDoIds: args, deferrable, dg0, updates = self.deferredDoIds[doId] dclass = args[2] if not dclass.getClassDef().neverDisable: return else: do = self.getDo(doId) if do: if not do.neverDisable: return AstronClientRepository.handleUpdateField(self, di) def handleDelete(self, di): doId = di.getUint32() self.deleteObject(doId) def _abandonShard(self): for doId, obj in self.doId2do.items(): if obj.parentId == localAvatar.defaultShard and obj is not localAvatar: self.deleteObject(doId) def handleEnterObjectRequiredOwner(self, di): if self.loginFSM.getCurrentState().getName( ) == 'waitForSetAvatarResponse': doId = di.getUint32() parentId = di.getUint32() zoneId = di.getUint32() dclassId = di.getUint16() self.__handleSetAvatarResponse(doId, di) else: AstronClientRepository.handleEnterObjectRequiredOwner(self, di) def addTaggedInterest(self, parentId, zoneId, mainTag, desc, otherTags=[], event=None): return self.addInterest(parentId, zoneId, desc, event) def sendSetAvatarMsg(self, choice): avId = choice.getAvId() self.sendSetAvatarIdMsg(avId) self.localAvChoice = choice def sendSetAvatarIdMsg(self, avId): if avId != self.__currentAvId: self.__currentAvId = avId self.csm.sendSetAvatar(avId) def sendQuietZoneRequest(self): self.sendSetZoneMsg(ZoneUtil.QuietZone)
class ToonFPS(DirectObject): notify = directNotify.newCategory('ToonFPS') WeaponName2DamageData = {'pistol': (36.0, 10.0, 150.0, 0.25), 'shotgun': (40.0, 15.0, 155.0, 0.5)} def __init__(self, mg, weaponName = 'pistol'): self.mg = mg self.weaponName = weaponName self.v_model_root = None self.v_model = None self.weapon = None self.track = None self.draw = None self.shoot = None self.reload = None self.empty = None self.cockBack = None self.cockFwd = None self.player_node = None self.shooterTrav = None self.shooterRay = None self.shooterRayNode = None self.shooterHandler = None self.gui = ToonFPSGui(self) self.fsm = ClassicFSM('ToonFPS', [State('off', self.enterOff, self.exitOff), State('alive', self.enterAlive, self.exitAlive), State('dead', self.enterDead, self.exitDead)], 'off', 'off') self.aliveFSM = ClassicFSM('alive', [State('off', self.enterOff, self.exitOff), State('draw', self.enterDraw, self.exitDraw, ['idle']), State('idle', self.enterIdle, self.exitIdle, ['shoot', 'reload']), State('shoot', self.enterShoot, self.exitShoot, ['idle']), State('reload', self.enterReload, self.exitReload, ['idle'])], 'off', 'off') self.fsm.getStateNamed('alive').addChild(self.aliveFSM) self.fsm.enterInitialState() self.aliveFSM.enterInitialState() if self.weaponName == 'pistol': self.ammo = 14 elif self.weaponName == 'shotgun': self.ammo = 7 self.hp = 125 self.max_hp = 125 self.firstPerson = FirstPerson() return def movementTask(self, task): if not inputState.isSet('jump') and not base.localAvatar.walkControls.isAirborne and inputState.isSet('forward') or inputState.isSet('reverse') or inputState.isSet('slideLeft') or inputState.isSet('slideRight'): if base.localAvatar.getAnimState() != 'run': base.localAvatar.setAnimState('run') base.localAvatar.playMovementSfx('run') self.mg.sendUpdate('runningAvatar', [base.localAvatar.doId]) elif inputState.isSet('jump') or base.localAvatar.walkControls.isAirborne: if base.localAvatar.getAnimState() != 'jump': base.localAvatar.setAnimState('jump') base.localAvatar.playMovementSfx(None) self.mg.sendUpdate('jumpingAvatar', [base.localAvatar.doId]) elif base.localAvatar.getAnimState() != 'neutral': base.localAvatar.setAnimState('neutral') base.localAvatar.playMovementSfx(None) self.mg.sendUpdate('standingAvatar', [base.localAvatar.doId]) return Task.cont def enterAlive(self): if self.mg.fsm.getCurrentState().getName() not in ('gameOver', 'announceGameOver', 'finalScores'): base.localAvatar.disableChatInput() self.start() self.resetHp() self.resetAmmo() if self.mg.fsm.getCurrentState().getName() == 'play': self.reallyStart() def exitAlive(self): self.end() self.v_model.reparentTo(hidden) if self.mg.fsm.getCurrentState().getName() != 'play': self.reallyEnd() base.localAvatar.createChatInput() def updatePoints(self): self.points = self.kills - self.deaths def enterDead(self, killer): base.localAvatar.getGeomNode().show() self.gui.end() base.localAvatar.attachCamera() self.freezeCamSfx = base.loadSfx('phase_4/audio/sfx/freeze_cam.wav') self.freezeCamImage = None self.freezeCamImageFile = None base.camera.setZ(base.camera.getZ() + 2.0) taskMgr.add(self.cameraLookAtKillerTask, 'lookAtKiller', extraArgs=[killer], appendTask=True) taskMgr.doMethodLater(2.0, self.startZoomOnKiller, 'startFreezeCam', extraArgs=[killer], appendTask=True) return def startZoomOnKiller(self, killer, task): taskMgr.add(self.__zoomOnKillerTask, 'zoomOnKiller', extraArgs=[killer], appendTask=True) return task.done def __zoomOnKillerTask(self, killer, task): if base.camera.getDistance(killer) <= 10.0 and self.freezeCamSfx.status() == self.freezeCamSfx.READY: base.playSfx(self.freezeCamSfx) if base.camera.getDistance(killer) < 7.0: self.doFreezeCam() return task.done base.camera.setY(base.camera, 60 * globalClock.getDt()) return task.again def doFreezeCam(self): taskMgr.remove('lookAtKiller') self.frameBuffer = PNMImage() base.win.getScreenshot(self.frameBuffer) self.freezeCamTex = Texture() self.freezeCamTex.load(self.frameBuffer) self.freezeCamImage = OnscreenImage(image=self.freezeCamTex, parent=render2d) def cameraLookAtKillerTask(self, killer, task): base.camera.lookAt(killer, 0, 0, 3) return task.cont def exitDead(self): taskMgr.remove('zoomOnKiller') taskMgr.remove('lookAtKiller') taskMgr.remove('startFreezeCam') del self.freezeCamSfx if self.freezeCamImage: self.freezeCamImage.destroy() del self.freezeCamImage self.frameBuffer.clear() self.freezeCamTex.clear() del self.frameBuffer del self.freezeCamTex base.localAvatar.detachCamera() base.localAvatar.getGeomNode().hide() self.gui.start() def load(self): if self.weaponName == 'pistol': self.draw = base.loadSfx('phase_4/audio/sfx/draw_secondary.wav') self.shoot = base.loadSfx('phase_4/audio/sfx/pistol_shoot.wav') self.reload = base.loadSfx('phase_4/audio/sfx/pistol_worldreload.wav') elif self.weaponName == 'shotgun': self.draw = base.loadSfx('phase_4/audio/sfx/draw_primary.wav') self.shoot = base.loadSfx('phase_4/audio/sfx/shotgun_shoot.wav') self.cockBack = base.loadSfx('phase_4/audio/sfx/shotgun_cock_back.wav') self.cockFwd = base.loadSfx('phase_4/audio/sfx/shotgun_cock_forward.wav') self.empty = base.loadSfx('phase_4/audio/sfx/shotgun_empty.wav') self.v_model_root = base.camera.attachNewNode('v_model_root') self.v_model = Actor('phase_4/models/minigames/v_dgm.egg', {'pidle': 'phase_4/models/minigames/v_dgm-pistol-idle.egg', 'pshoot': 'phase_4/models/minigames/v_dgm-pistol-shoot.egg', 'preload': 'phase_4/models/minigames/v_dgm-pistol-reload.egg', 'pdraw': 'phase_4/models/minigames/v_dgm-pistol-draw.egg', 'sidle': 'phase_4/models/minigames/v_dgm-shotgun-idle.egg', 'sshoot': 'phase_4/models/minigames/v_dgm-shotgun-shoot.egg'}) if self.weaponName == 'pistol': self.weapon = loader.loadModel('phase_4/models/props/water-gun.bam') self.weapon.reparentTo(self.v_model.exposeJoint(None, 'modelRoot', 'Bone.011')) self.weapon.setX(-0.125) self.weapon.setY(0.5) self.weapon.setScale(0.65) elif self.weaponName == 'shotgun': self.weapon = loader.loadModel('phase_4/models/props/shotgun.egg') self.weapon.reparentTo(self.v_model.exposeJoint(None, 'modelRoot', 'Bone.029')) self.weapon.setScale(0.75) self.weapon.setPos(0.45, -1.03, -1.17) self.weapon.setHpr(9.46, 308.19, 75.78) color = random.choice([VBase4(1, 0.25, 0.25, 1), VBase4(0.25, 1, 0.25, 1), VBase4(0.25, 0.25, 1, 1)]) self.weapon.setColorScale(color) self.gui.load() return def start(self): base.camLens.setNear(0.1) self.shooterTrav = CollisionTraverser('ToonFPS.shooterTrav') ray = CollisionRay() rayNode = CollisionNode('ToonFPS.rayNode') rayNode.addSolid(ray) rayNode.setCollideMask(BitMask32(0)) rayNode.setFromCollideMask(CIGlobals.WallBitmask | CIGlobals.FloorBitmask) self.shooterRay = ray self.shooterRayNode = base.camera.attachNewNode(rayNode) self.shooterHandler = CollisionHandlerQueue() self.shooterTrav.addCollider(self.shooterRayNode, self.shooterHandler) self.firstPerson.start() self.v_model_root.reparentTo(base.camera) self.v_model.reparentTo(self.v_model_root) if self.weaponName == 'pistol': self.v_model_root.setZ(-1.8) self.v_model_root.setY(0.3) self.v_model_root.setX(-0.1) self.v_model_root.setH(2) elif self.weaponName == 'shotgun': self.v_model_root.setPos(-0.42, -0.81, -1.7) self.v_model_root.setHpr(359, 352.87, 0.0) self.gui.start() self.firstPerson.disableMouse() self.aliveFSM.request('draw') def reallyStart(self): self.firstPerson.reallyStart() taskMgr.add(self.movementTask, 'toonBattleMovement') def end(self): self.aliveFSM.request('off') if self.firstPerson: self.firstPerson.enableMouse() self.firstPerson.end() taskMgr.remove('toonBattleMovement') if self.mg.fsm.getCurrentState().getName() != 'play': self.fsm.request('off') def reallyEnd(self): if self.shooterRayNode: self.shooterRayNode.removeNode() self.shooterRayNode = None self.shooterRay = None self.shooterTrav = None self.shooterHandler = None if self.firstPerson: self.firstPerson.reallyEnd() if self.v_model_root: self.v_model_root.reparentTo(hidden) if self.v_model: self.v_model.reparentTo(hidden) self.v_model.setPosHpr(0, 0, 0, 0, 0, 0) if self.gui: self.gui.end() base.camLens.setNear(1.0) return def cleanup(self): taskMgr.remove('lookAtKiller') taskMgr.remove('toonBattleMovement') if self.firstPerson: self.firstPerson.cleanup() self.firstPerson = None self.draw = None self.shoot = None self.reload = None self.empty = None self.ammo = None self.fsm = None self.aliveFSM = None self.player_node = None self.min_camerap = None self.max_camerap = None self.hp = None self.max_hp = None if self.v_model: self.v_model.cleanup() self.v_model = None if self.weapon: self.weapon.removeNode() self.weapon = None if self.weapon: self.v_model_root.removeNode() self.v_model_root = None if self.gui: self.gui.cleanup() return def damageTaken(self, amount, avId): if self.hp <= 0.0: killer = self.mg.cr.doId2do.get(avId, None) self.fsm.request('dead', [killer]) self.gui.adjustHpMeter() return def enterDraw(self): self.draw.play() if self.weaponName == 'pistol': self.track = ActorInterval(self.v_model, 'pdraw', playRate=1.6, name='drawTrack') elif self.weaponName == 'shotgun': self.v_model.pose('sidle', 15) self.track = LerpQuatInterval(self.v_model, duration=0.5, quat=(0, 0, 0), startHpr=(70, -50, 0), blendType='easeOut', name='drawTrack') self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() def exitDraw(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None return def enterIdle(self): if self.weaponName == 'pistol': self.v_model.loop('pidle') elif self.weaponName == 'shotgun': self.track = Sequence(LerpQuatInterval(self.v_model, duration=2.0, quat=(0, 1, 0), startHpr=(0, 0, 0), blendType='easeInOut'), LerpQuatInterval(self.v_model, duration=2.0, quat=(0, 0, 0), startHpr=(0, 1, 0), blendType='easeInOut')) self.track.loop() self.accept('mouse1', self.requestShoot) if self.ammo <= 0: self.gui.notifyNoAmmo() if self.ammo < 14: self.accept('r', self.aliveFSM.request, ['reload']) def requestShoot(self): if self.mg.fsm.getCurrentState().getName() != 'play': return if self.ammo > 0: self.aliveFSM.request('shoot') else: self.empty.play() def exitIdle(self): self.v_model.stop() if self.track: self.track.finish() self.track = None self.ignore('mouse1') self.ignore('r') return def enterShoot(self): self.shoot.play() if self.weaponName == 'pistol': self.track = ActorInterval(self.v_model, 'pshoot', playRate=2, name='shootTrack') elif self.weaponName == 'shotgun': self.track = Parallel(Sequence(LerpQuatInterval(self.v_model, duration=0.05, quat=(0, 3, 0), startHpr=(0, 0, 0)), LerpQuatInterval(self.v_model, duration=0.1, quat=(0, 0, 0), startHpr=(0, 3, 0))), Sequence(LerpPosInterval(self.v_model, duration=0.05, pos=(0, -0.3, 0), startPos=(0, 0, 0)), LerpPosInterval(self.v_model, duration=0.1, pos=(0, 0, 0), startPos=(0, -0.3, 0)), Wait(0.1))) self.track.setDoneEvent('shootTrack') self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() self.ammo -= 1 self.gui.adjustAmmoGui() self.mg.makeSmokeEffect(self.weapon.find('**/joint_nozzle').getPos(render)) self.traverse() def traverse(self): mpos = base.mouseWatcherNode.getMouse() self.shooterRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.shooterTrav.traverse(render) def calcDamage(self, avatar): dmgData = self.WeaponName2DamageData[self.weaponName] maxDamage = dmgData[0] minDistance = dmgData[1] maxDistance = dmgData[2] factor = dmgData[3] distance = base.localAvatar.getDistance(avatar) if distance < minDistance: distance = minDistance elif distance > maxDistance: distance = maxDistance damage = maxDamage - (distance - minDistance) * factor return damage def exitShoot(self): self.ignore('shootTrack') if self.track: self.track.finish() self.track = None return def enterReload(self): self.gui.deleteNoAmmoLabel() if self.weaponName == 'pistol': self.track = Parallel(Sequence(Wait(0.3), Func(self.reload.play), Func(self.resetAmmo)), ActorInterval(self.v_model, 'preload', playRate=1.5), name='reloadTrack') elif self.weaponName == 'shotgun': self.track = Sequence(Func(self.draw.play), LerpQuatInterval(self.v_model, duration=0.5, quat=(70, -50, 0), startHpr=(0, 0, 0), blendType='easeIn'), SoundInterval(self.cockBack), SoundInterval(self.cockFwd), Func(self.resetAmmo), Func(self.draw.play), LerpQuatInterval(self.v_model, duration=0.5, quat=(0, 0, 0), startHpr=(70, -50, 0), blendType='easeOut'), name='reloadTrack') self.track.setDoneEvent('reloadTrack') self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() def exitReload(self): self.ignore('reloadTrack') if self.track: self.track.finish() self.track = None return def resetAmmo(self): if self.weaponName == 'pistol': self.ammo = 14 elif self.weaponName == 'shotgun': self.ammo = 7 self.gui.resetAmmo() def resetHp(self): self.hp = self.max_hp self.gui.adjustHpMeter() def enterOff(self): pass def exitOff(self): pass
class DistributedDoor(DistributedObject.DistributedObject): notify = directNotify.newCategory("DistributedDoor") notify.setInfo(True) INT_STANDARD = 0 EXT_STANDARD = 1 INT_HQ = 2 EXT_HQ = 3 EXT_GAGSHOP = 4 LIT_INTERIOR_COLOR = Vec4(1.0, 236.0 / 255.0, 142.0 / 255.0, 1.0) def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.rightFSM = ClassicFSM( 'DistributedDoor_right', [ State('off', self.enterOff, self.exitOff), State('closed', self.enterRightDoorClosed, self.exitRightDoorClosed, ['opening']), State('opening', self.enterRightDoorOpening, self.exitRightDoorOpening, ['open']), State('open', self.enterRightDoorOpen, self.exitRightDoorOpen, ['closing']), State('closing', self.enterRightDoorClosing, self.exitRightDoorClosing, ['closed']) ], 'off', 'off' ) self.rightFSM.enterInitialState() self.leftFSM = ClassicFSM( 'DistributedDoor_left', [ State('off', self.enterOff, self.exitOff), State('closed', self.enterLeftDoorClosed, self.exitLeftDoorClosed, ['opening']), State('opening', self.enterLeftDoorOpening, self.exitLeftDoorOpening, ['open']), State('open', self.enterLeftDoorOpen, self.exitLeftDoorOpen, ['closing']), State('closing', self.enterLeftDoorClosing, self.exitLeftDoorClosing, ['closed']) ], 'off', 'off' ) self.leftFSM.enterInitialState() self.avatarTracks = [] self.leftDoorState = '' self.rightDoorState = '' self.toZone = 0 self.block = 0 self.doorType = 0 self.doorIndex = 0 self.leftTrack = None self.rightTrack = None self.building = None self.doorNode = None self.leftDoor = None self.rightDoor = None self.doorOpenSound = None self.doorShutSound = None self.enterDoorWalkBackNode = None self.enterDoorWalkInNode = None self.exitDoorWalkFromNode = None self.exitDoorWalkToNode = None self.ready = False self.nodeProblemPolled = False self.suitTakingOver = 0 def setSuitTakingOver(self, flag): self.suitTakingOver = flag def getSuitTakingOver(self): return self.suitTakingOver def setDoorIndex(self, index): self.doorIndex = index def getDoorIndex(self): return self.doorIndex def getLeftDoorOpenH(self): num = 0 if self.getDoorType() == self.INT_STANDARD or self.getDoorType() == self.INT_HQ: num = 70 elif self.getDoorType() == self.EXT_STANDARD or self.getDoorType() == self.EXT_HQ: num = -110 if (self.getDoorIndex() == 1 and not self.doorType == self.EXT_HQ or self.getDoorIndex() == 0 and self.doorType in [self.EXT_HQ, self.EXT_GAGSHOP]): return num - 180 else: return num def getLeftDoorClosedH(self): num = 0 if self.getDoorType() == self.INT_STANDARD or self.getDoorType() == self.INT_HQ: num = 180 elif self.getDoorType() == self.EXT_STANDARD or self.getDoorType() == self.EXT_HQ: num = 0 if (self.getDoorIndex() == 1 and not self.doorType == self.EXT_HQ or self.getDoorIndex() == 0 and self.doorType in [self.EXT_HQ, self.EXT_GAGSHOP]): return num - 180 else: return num def getRightDoorOpenH(self): num = 0 if self.getDoorType() == self.INT_STANDARD or self.getDoorType() == self.INT_HQ: num = -70 elif self.getDoorType() == self.EXT_STANDARD or self.getDoorType() == self.EXT_HQ or self.getDoorType() == self.EXT_GAGSHOP: num = 110 if (self.getDoorIndex() == 1 and not self.doorType == self.EXT_HQ or self.getDoorIndex() == 0 and self.doorType in [self.EXT_HQ, self.EXT_GAGSHOP]): return num - 180 else: return num def getRightDoorClosedH(self): num = 0 if self.getDoorType() == self.INT_STANDARD or self.getDoorType() == self.INT_HQ: num = 180 elif self.getDoorType() == self.EXT_STANDARD or self.getDoorType() == self.EXT_HQ or self.getDoorType() == self.EXT_GAGSHOP: num = 0 if (self.getDoorIndex() == 1 and not self.doorType == self.EXT_HQ or self.getDoorIndex() == 0 and self.doorType in [self.EXT_HQ, self.EXT_GAGSHOP]): return num - 180 else: return num def enterOff(self, ts = 0): pass def exitOff(self): pass def enterRightDoorClosed(self, ts = 0): self.rightDoor.setH(self.getRightDoorClosedH()) self.toggleDoorHole('Right', show = False) def exitRightDoorClosed(self): pass def enterRightDoorOpen(self, ts = 0): self.rightDoor.setH(self.getRightDoorOpenH()) def exitRightDoorOpen(self): pass def enterRightDoorClosing(self, ts = 0): if self.rightTrack: self.rightTrack.finish() self.rightTrack = None self.rightTrack = Sequence(LerpQuatInterval(self.rightDoor, duration = 1.0, quat = (self.getRightDoorClosedH(), 0, 0), startHpr = (self.getRightDoorOpenH(), 0, 0), blendType = 'easeIn'), Func(base.playSfx, self.doorShutSound, 0, 1, None, 0.0, self.rightDoor)) self.rightTrack.start() def exitRightDoorClosing(self): if self.rightTrack: self.rightTrack.finish() self.rightTrack = None def enterRightDoorOpening(self, ts = 0): self.toggleDoorHole('Right', show = True) self.rightDoor.show() if self.rightTrack: self.rightTrack.finish() self.rightTrack = None self.rightTrack = Sequence(Wait(0.5), Parallel(LerpQuatInterval(self.rightDoor, duration = 0.7, quat = (self.getRightDoorOpenH(), 0, 0), startHpr = (self.getRightDoorClosedH(), 0, 0), blendType = 'easeInOut'), SoundInterval(self.doorOpenSound, node = self.rightDoor))) self.rightTrack.start() def exitRightDoorOpening(self): if self.rightTrack: self.rightTrack.finish() self.rightTrack = None def enterLeftDoorClosed(self, ts = 0): self.leftDoor.setH(self.getLeftDoorClosedH()) self.toggleDoorHole('Left', show = False) def exitLeftDoorClosed(self): pass def enterLeftDoorOpen(self, ts = 0): self.leftDoor.setH(self.getLeftDoorOpenH()) def exitLeftDoorOpen(self): pass def enterLeftDoorClosing(self, ts = 0): if self.leftTrack: self.leftTrack.finish() self.leftTrack = None self.leftTrack = Sequence(LerpQuatInterval( self.leftDoor, duration = 1.0, quat = (self.getLeftDoorClosedH(), 0, 0), startHpr = (self.getLeftDoorOpenH(), 0, 0), blendType = 'easeIn'), Func(base.playSfx, self.doorShutSound, 0, 1, None, 0.0, self.leftDoor)) self.leftTrack.start() def exitLeftDoorClosing(self): if self.leftTrack: self.leftTrack.finish() self.leftTrack = None def enterLeftDoorOpening(self, ts = 0): self.toggleDoorHole('Left', show = True) self.leftDoor.show() if self.leftTrack: self.leftTrack.finish() self.leftTrack = None self.leftTrack = Sequence(Wait(0.5), Parallel(LerpQuatInterval(self.leftDoor, duration = 0.7, quat = (self.getLeftDoorOpenH(), 0, 0), startHpr = (self.getLeftDoorClosedH(), 0, 0), blendType = 'easeInOut'), SoundInterval(self.doorOpenSound, node = self.leftDoor))) self.leftTrack.start() def exitLeftDoorOpening(self): if self.leftTrack: self.leftTrack.finish() self.leftTrack = None def setDoorType(self, door): self.doorType = door def getDoorType(self): return self.doorType def setBlock(self, block): self.block = block def getBlock(self): return self.block def setToZone(self, zone): self.toZone = zone def getToZone(self): return self.toZone def setLeftDoorState(self, state, timestamp): ts = ClockDelta.globalClockDelta.localElapsedTime(timestamp) self.leftDoorState = state if self.building: self.leftFSM.request(state, [ts]) def getLeftDoorState(self): return self.leftDoorState def setRightDoorState(self, state, timestamp): ts = ClockDelta.globalClockDelta.localElapsedTime(timestamp) self.rightDoorState = state if self.building: self.rightFSM.request(state, [ts]) def getRightDoorState(self): return self.rightDoorState def findBuilding(self): bldg = None if self.getDoorType() == self.EXT_STANDARD or self.getDoorType() == self.EXT_HQ or self.getDoorType() == self.EXT_GAGSHOP: bldg = self.cr.playGame.hood.loader.geom.find('**/??' + str(self.getBlock()) + ':*_landmark_*_DNARoot;+s') elif self.getDoorType() == self.INT_STANDARD: bldg = render.find('**/leftDoor;+s').getParent() elif self.getDoorType() == self.INT_HQ: bldg = render.find('**/door_origin_0').getParent() return bldg def findDoorNodePath(self): doorNode = None if self.getDoorType() in [self.EXT_STANDARD, self.EXT_GAGSHOP]: doorNode = self.building.find('**/*door_origin') elif self.getDoorType() == self.EXT_HQ: doorNode = self.building.find('**/door_origin_' + str(self.doorIndex)) elif self.getDoorType() == self.INT_STANDARD: doorNode = render.find('**/door_origin') elif self.getDoorType() == self.INT_HQ: doorNode = render.find('**/door_origin_' + str(self.doorIndex)) return doorNode def findDoorNode(self, string): if self.doorType != self.INT_HQ: foundNode = self.building.find('**/door_' + str(self.getDoorIndex()) + '/**/' + string + '*;+s+i') if foundNode.isEmpty(): foundNode = self.building.find('**/' + string + '*;+s+i') else: foundNode = render.find('**/door_' + str(self.getDoorIndex()) + '/**/' + string + '*;+s+i') if foundNode.isEmpty(): foundNode = render.find('**/' + string + '*;+s+i') return foundNode def getTriggerName(self): if self.getDoorType() == self.INT_STANDARD or self.getDoorType() == self.EXT_STANDARD or self.getDoorType() == self.EXT_GAGSHOP: return 'door_trigger_' + str(self.getBlock()) elif self.getDoorType() == self.INT_HQ or self.getDoorType() == self.EXT_HQ: return 'door_trigger_' + str(self.block) + '0' + str(self.doorIndex) def getEnterTriggerEvent(self): return 'enter' + self.getTriggerName() def getExitTriggerEvent(self): return 'exit' + self.getTriggerName() def __pollBuilding(self, task): try: self.building = self.findBuilding() except: return task.cont if self.building.isEmpty(): return task.cont self.generated() return task.done def _handleTrigger(self, ghostNode): if not self.getSuitTakingOver(): self.cr.playGame.getPlace().fsm.request('stop') base.localAvatar.walkControls.setCollisionsActive(0) self.sendUpdate('requestEnter', []) def getAvatarEnterTrack(self, av): track = Sequence(name = av.uniqueName('avatarEnterDoorTrack')) track.append(Func(av.setAnimState, 'walkBack')) track.append( ParallelEndTogether( LerpPosInterval( av, duration = 0.5, blendType = 'easeInOut', pos = self.enterWalkBackPos, startPos = av.getPos(render) ), LerpQuatInterval( av, duration = 0.5, hpr = self.doorNode.getHpr(render), startHpr = av.getHpr(render) ) ) ) track.append(Func(av.setPlayRate, 1.0, 'walk')) track.append(Func(av.loop, 'neutral')) track.append(Wait(1.0)) track.append(Func(av.loop, 'walk')) parallel = Parallel() parallel.append( LerpPosInterval( av, duration = 1.0, blendType = 'easeInOut', pos = self.enterWalkInPos, startPos = self.enterWalkBackPos ) ) if base.localAvatar.doId == av.doId: parallel.append(LerpPosHprInterval(nodePath = camera, other = av, duration = 1.0, pos = (0, -8, av.getHeight()), hpr = (0, 0, 0), blendType = 'easeInOut')) parallel.append(Sequence(Wait(0.5), Func(self.sendGoingIn), Wait(1.0))) track.append(parallel) if base.localAvatar.doId == av.doId: track.append(Func(self.sendWentInDoor)) track.setDoneEvent(track.getName()) track.delayDelete = DelayDelete.DelayDelete(av, track.getName()) self.acceptOnce(track.getDoneEvent(), self.__avatarTrackDone, [track]) return track def sendGoingIn(self): messenger.send('DistributedDoor_localAvatarGoingInDoor') def sendWentInDoor(self): messenger.send('DistributedDoor_localAvatarWentInDoor') def getAvatarExitTrack(self, av): track = Sequence(name = av.uniqueName('avatarExitDoorTrack')) track.append(Wait(1.3)) track.append(Func(av.setAnimState, 'walk')) av.setPos(self.exitWalkFromPos) av.headsUp(self.exitWalkToPos) track.append( LerpPosInterval( av, duration = 1.2, blendType = 'easeInOut', pos = self.exitWalkToPos, startPos = av.getPos(render) ) ) track.append(Func(av.loop, 'neutral')) if base.localAvatar.doId == av.doId: track.append(Func(messenger.send, 'DistributedDoor_localAvatarCameOutOfDoor')) else: track.append(Func(av.startSmooth)) track.setDoneEvent(track.getName()) track.delayDelete = DelayDelete.DelayDelete(av, track.getName()) self.acceptOnce(track.getDoneEvent(), self.__avatarTrackDone, [track]) return track def __avatarTrackDone(self, track): if track: DelayDelete.cleanupDelayDeletes(track) if self.avatarTracks: self.avatarTracks.remove(track) def enterDoor(self, avatarId, timestamp): if not self.building: return ts = ClockDelta.globalClockDelta.localElapsedTime(timestamp) if avatarId == base.localAvatar.doId: self.cr.playGame.getPlace().fsm.request('doorIn', [self]) av = self.cr.doId2do.get(avatarId) if av: av.stopSmooth() track = self.getAvatarEnterTrack(av) self.avatarTracks.append(track) track.start() def exitDoor(self, avatarId, timestamp): if not self.building: return ts = ClockDelta.globalClockDelta.localElapsedTime(timestamp) av = self.cr.doId2do.get(avatarId) if av: if av.doId != base.localAvatar.doId: av.stopSmooth() track = self.getAvatarExitTrack(av) self.avatarTracks.append(track) track.start() def announceGenerate(self): DistributedObject.DistributedObject.announceGenerate(self) try: self.building = self.findBuilding() self.generated() except: self.startBuildingPoll() return if self.building.isEmpty(): self.startBuildingPoll() return def startBuildingPoll(self): base.taskMgr.add(self.__pollBuilding, self.uniqueName('pollBuilding')) def fixHQTrigger(self): trig = self.building.find('**/door_' + str(self.doorIndex) + '/**/door_trigger*') if not trig.isEmpty(): trig.node().setName(self.getTriggerName()) def generated(self): self.doorNode = self.findDoorNodePath() self.rightDoor = self.findDoorNode('rightDoor') self.leftDoor = self.findDoorNode('leftDoor') self.toggleDoorHole('Right', show = False) self.toggleDoorHole('Left', show = False) self.enterWalkBackPos = render.getRelativePoint(self.doorNode, Point3(1.6, -5.5, 0.0)) self.enterWalkInPos = render.getRelativePoint(self.doorNode, Point3(1.6, 3.0, 0.0)) self.exitWalkFromPos = render.getRelativePoint(self.doorNode, Point3(-1.6, 3.0, 0.0)) self.exitWalkToPos = render.getRelativePoint(self.doorNode, Point3(-1.6, -5.5, 0.0)) self.doorOpenSound = base.audio3d.loadSfx('phase_3.5/audio/sfx/Door_Open_1.ogg') self.doorShutSound = base.audio3d.loadSfx('phase_3.5/audio/sfx/Door_Close_1.ogg') base.audio3d.attachSoundToObject(self.doorOpenSound, self.doorNode) base.audio3d.attachSoundToObject(self.doorShutSound, self.doorNode) if self.doorType == self.EXT_HQ: self.fixHQTrigger() self.acceptOnce(self.getEnterTriggerEvent(), self._handleTrigger) self.ready = True def toggleDoorHole(self, side, show = False): side = side.title() if self.building: isDDL = self.cr.playGame.hood.id == DonaldsDreamland isExt = self.getDoorType() in [self.EXT_GAGSHOP, self.EXT_HQ, self.EXT_STANDARD] holeColor = self.LIT_INTERIOR_COLOR if (isExt and isDDL) else (0.0, 0.0, 0.0, 1.0) if self.getDoorType() == self.EXT_HQ: hole = self.building.find('**/doorFrameHole%s_%d' % (side, self.doorIndex)) geom = self.building.find('**/doorFrameHole%sGeom_%d' % (side, self.doorIndex)) if not hole or hole.isEmpty(): doorFlats = self.building.findAllMatches('**/door_fla*;+s+i') for doorFlat in doorFlats: if not doorFlat.isEmpty() and int(doorFlat.getName()[len(doorFlat.getName()) - 1]) == self.doorIndex: # Let's reset the material to the default white. doorFlat.setBSPMaterial('phase_14/materials/white.mat', 1) # This is a hacky way to make sure the flat part is behind the door. # This took me like 2 hours to figure out this workaround. Don't question it # with some stupid #setPos() trash, depth write/depth test, or any of that. This works. doorFlat.setSy(0.995) hole = doorFlat break elif self.getDoorType() == self.INT_HQ: hole = render.find('**/door_' + str(self.doorIndex) + '/**/doorFrameHole%s;+s+i' % side) geom = render.find('**/door_' + str(self.doorIndex) + '/**/doorFrameHole%sGeom;+s+i' % side) else: hole = self.building.find('**/doorFrameHole%s' % side) geom = self.building.find('**/doorFrameHole%sGeom' % side) nodes = [hole, geom] for node in nodes: if node and not node.isEmpty(): if show: node.show() else: node.hide() node.setColor(holeColor, 1) def printBuildingPos(self): self.notify.info(self.building.getPos(render)) def disable(self): self.ignore(self.getEnterTriggerEvent()) base.taskMgr.remove(self.uniqueName('pollBuilding')) for track in self.avatarTracks: track.finish() self.avatarTracks = None self.building = None self.doorNode = None self.rightDoor = None self.leftDoor = None self.ready = None self.toZone = None if self.leftTrack: self.leftTrack.finish() self.leftTrack = None if self.rightTrack: self.rightTrack.finish() self.rightTrack = None if self.enterDoorWalkBackNode: self.enterDoorWalkBackNode.removeNode() self.enterDoorWalkBackNode = None if self.enterDoorWalkInNode: self.enterDoorWalkInNode.removeNode() self.enterDoorWalkInNode = None if self.exitDoorWalkFromNode: self.exitDoorWalkFromNode.removeNode() self.exitDoorWalkFromNode = None if self.exitDoorWalkToNode: self.exitDoorWalkToNode.removeNode() self.exitDoorWalkToNode = None self.doorOpenSound = None self.doorShutSound = None self.leftDoorState = None self.rightDoorState = None self.block = None self.doorType = None self.doorIndex = None self.nodeProblemPolled = None self.suitTakingOver = None DistributedObject.DistributedObject.disable(self)
class Char(Avatar.Avatar): def __init__(self): try: self.Char_initialized return except: self.Char_initialized = 1 Avatar.Avatar.__init__(self) self.avatarType = CIGlobals.CChar self.avatarName = None self.currentAnim = None self.charType = '' self.eyes = loader.loadTexture('phase_3/maps/eyes1.jpg', 'phase_3/maps/eyes1_a.rgb') self.closedEyes = loader.loadTexture('phase_3/maps/mickey_eyes_closed.jpg', 'phase_3/maps/mickey_eyes_closed_a.rgb') self.animFSM = ClassicFSM('Char', [State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('walk', self.enterWalk, self.exitWalk), State('run', self.enterRun, self.exitRun)], 'off', 'off') animStateList = self.animFSM.getStates() self.animFSM.enterInitialState() Avatar.Avatar.initializeBodyCollisions(self, self.avatarType, 3.5, 1) return def getNametagJoints(self): return [] def stopAnimations(self): if hasattr(self, 'animFSM'): if not self.animFSM.isInternalStateInFlux(): self.animFSM.request('off') else: notify.warning('animFSM in flux, state=%s, not requesting off' % self.animFSM.getCurrentState().getName()) else: notify.warning('animFSM has been deleted') def disable(self): self.stopBlink() self.stopAnimations() Avatar.Avatar.disable(self) def delete(self): try: self.Char_deleted except: self.Char_deleted = 1 del self.animFSM Avatar.Avatar.delete(self) def setChat(self, chatString): if self.charType == CIGlobals.Mickey: self.dial = base.audio3d.loadSfx('phase_3/audio/dial/mickey.ogg') else: if self.charType == CIGlobals.Minnie: self.dial = base.audio3d.loadSfx('phase_3/audio/dial/minnie.ogg') else: if self.charType == CIGlobals.Goofy: self.dial = base.audio3d.loadSfx('phase_6/audio/dial/goofy.ogg') base.audio3d.attachSoundToObject(self.dial, self) self.dial.play() Avatar.Avatar.setChat(self, chatString) def setName(self, nameString, charName=None): self.avatarName = nameString Avatar.Avatar.setName(self, nameString, avatarType=self.avatarType, charName=charName) def setupNameTag(self, tempName=None): Avatar.Avatar.setupNameTag(self, tempName) self.nametag.setNametagColor(NametagGlobals.NametagColors[NametagGlobals.CCNPC]) self.nametag.setActive(0) self.nametag.updateAll() def generateChar(self, charType): self.charType = charType if charType == CIGlobals.Mickey or charType == CIGlobals.Minnie: self.loadModel('phase_3/models/char/' + charType.lower() + '-' + str(CIGlobals.ModelDetail(self.avatarType)) + '.bam') self.loadAnims({'neutral': 'phase_3/models/char/' + charType.lower() + '-wait.bam', 'walk': 'phase_3/models/char/' + charType.lower() + '-walk.bam', 'run': 'phase_3/models/char/' + charType.lower() + '-run.bam', 'left-start': 'phase_3.5/models/char/' + charType.lower() + '-left-start.bam', 'left': 'phase_3.5/models/char/' + charType.lower() + '-left.bam', 'right-start': 'phase_3.5/models/char/' + charType.lower() + '-right-start.bam', 'right': 'phase_3.5/models/char/' + charType.lower() + '-right.bam'}) if charType == CIGlobals.Mickey: self.mickeyEye = self.controlJoint(None, 'modelRoot', 'joint_pupilR') self.mickeyEye.setY(0.025) for bundle in self.getPartBundleDict().values(): bundle = bundle['modelRoot'].getBundle() earNull = bundle.findChild('sphere3') if not earNull: earNull = bundle.findChild('*sphere3') earNull.clearNetTransforms() for bundle in self.getPartBundleDict().values(): charNodepath = bundle['modelRoot'].partBundleNP bundle = bundle['modelRoot'].getBundle() earNull = bundle.findChild('sphere3') if not earNull: earNull = bundle.findChild('*sphere3') ears = charNodepath.find('**/sphere3') if ears.isEmpty(): ears = charNodepath.find('**/*sphere3') ears.clearEffect(CharacterJointEffect.getClassType()) earRoot = charNodepath.attachNewNode('earRoot') earPitch = earRoot.attachNewNode('earPitch') earPitch.setP(40.0) ears.reparentTo(earPitch) earNull.addNetTransform(earRoot.node()) ears.clearMat() ears.node().setPreserveTransform(ModelNode.PTNone) ears.setP(-40.0) ears.flattenMedium() ears.setBillboardAxis() self.startBlink() else: if charType == CIGlobals.Pluto: self.loadModel('phase_6/models/char/pluto-1000.bam') self.loadAnims({'walk': 'phase_6/models/char/pluto-walk.bam', 'neutral': 'phase_6/models/char/pluto-neutral.bam', 'sit': 'phase_6/models/char/pluto-sit.bam', 'stand': 'phase_6/models/char/pluto-stand.bam'}) else: if charType == CIGlobals.Goofy: self.loadModel('phase_6/models/char/TT_G-1500.bam') self.loadAnims({'neutral': 'phase_6/models/char/TT_GWait.bam', 'walk': 'phase_6/models/char/TT_GWalk.bam'}) else: raise StandardError('unknown char %s!' % charType) Avatar.Avatar.initShadow(self) return def initializeLocalCollisions(self, name, radius): Avatar.Avatar.initializeLocalCollisions(self, radius, 2, name) def startBlink(self): randomStart = random.uniform(0.5, 5) taskMgr.add(self.blinkTask, 'blinkTask') def stopBlink(self): taskMgr.remove('blinkTask') taskMgr.remove('doBlink') taskMgr.remove('openEyes') def blinkTask(self, task): taskMgr.add(self.doBlink, 'doBlink') delay = random.uniform(0.5, 7) task.delayTime = delay return task.again def doBlink(self, task): self.closeEyes() taskMgr.doMethodLater(0.2, self.openEyes, 'openEyes') return task.done def closeEyes(self): self.find('**/joint_pupilR').hide() self.find('**/joint_pupilL').hide() if self.charType == CIGlobals.Mickey: self.mickeyEye.setY(-0.025) self.mickeyEye.hide() self.find('**/eyes').setTexture(self.closedEyes, 1) def openEyes(self, task): self.find('**/joint_pupilR').show() self.find('**/joint_pupilL').show() if self.charType == CIGlobals.Mickey: self.mickeyEye.setY(0.025) self.mickeyEye.show() self.find('**/eyes').setTexture(self.eyes, 1) return task.done def enterOff(self): self.currentAnim = None return def exitOff(self): pass def enterNeutral(self): self.loop('neutral') def exitNeutral(self): self.stop() def enterWalk(self): self.loop('walk') def exitWalk(self): self.stop() def enterRun(self): self.loop('run') def exitRun(self): self.stop()
class CameraShyFirstPerson(FirstPerson): toonInFocusColor = VBase4(0.25, 1.0, 0.25, 1.0) toonOutOfFocusColor = VBase4(1.0, 1.0, 1.0, 1.0) fullyChargedState = 5 def __init__(self, mg): self.mg = mg self.cameraFocus = None self.batteryFrame = None self.batteryBg = None self.batteryBar = None self.rechargeSound = None self.fullyChargedSound = None self.hasToonInFocus = False self.toonToTakePicOf = None self.cameraRechargeState = None self.cameraRechargingLabel = None self.cameraFlashSeq = None self.camFSM = ClassicFSM('CameraFSM', [State('off', self.enterOff, self.exitOff), State('ready', self.enterCameraReady, self.exitCameraReady), State('recharge', self.enterCameraRecharge, self.exitCameraRecharge)], 'off', 'off') self.camFSM.enterInitialState() FirstPerson.__init__(self) return def movementTask(self, task): if not inputState.isSet('jump') and not base.localAvatar.walkControls.isAirborne and inputState.isSet('forward') or inputState.isSet('reverse') or inputState.isSet('slideLeft') or inputState.isSet('slideRight'): if base.localAvatar.getAnimState() != 'run': base.localAvatar.setAnimState('run') base.localAvatar.playMovementSfx('run') self.mg.sendUpdate('runningAvatar', [base.localAvatar.doId]) elif inputState.isSet('jump') or base.localAvatar.walkControls.isAirborne: if base.localAvatar.getAnimState() != 'jump': base.localAvatar.setAnimState('jump') base.localAvatar.playMovementSfx(None) self.mg.sendUpdate('jumpingAvatar', [base.localAvatar.doId]) elif base.localAvatar.getAnimState() != 'neutral': base.localAvatar.setAnimState('neutral') base.localAvatar.playMovementSfx(None) self.mg.sendUpdate('standingAvatar', [base.localAvatar.doId]) return task.cont def enterOff(self): pass def exitOff(self): pass def enterCameraReady(self): self.acceptOnce('mouse1', self.__mouse1Pressed) def stopCameraFlash(self): if self.cameraFlashSeq: self.cameraFlashSeq.finish() self.cameraFlashSeq = None return def __mouse1Pressed(self): self.cameraFlashSeq = Sequence(Func(base.transitions.setFadeColor, 1, 1, 1), Func(base.transitions.fadeOut, 0.1), Wait(0.1), Func(base.transitions.fadeIn, 0.1), Wait(0.1), Func(base.transitions.setFadeColor, 0, 0, 0)) self.cameraFlashSeq.start() self.mg.sendUpdate('remoteAvatarTakePicture', [base.localAvatar.doId]) self.mg.myRemoteAvatar.takePicture() if self.hasToonInFocus and self.toonToTakePicOf: self.mg.sendUpdate('tookPictureOfToon', [self.toonToTakePicOf.doId]) self.camFSM.request('recharge') def exitCameraReady(self): self.ignore('mouse1') def enterCameraRecharge(self): self.batteryBar.update(0) taskMgr.add(self.__rechargeNextState, 'rechargeCamera') def __rechargeNextState(self, task): if self.cameraRechargeState == None: self.cameraRechargeState = -1 self.cameraRechargeState += 1 if self.cameraRechargeState > 0: base.playSfx(self.rechargeSound) self.batteryBar.update(self.cameraRechargeState) if self.cameraRechargeState == self.fullyChargedState: base.playSfx(self.fullyChargedSound) self.camFSM.request('ready') return task.done else: task.delayTime = 1.0 return task.again def exitCameraRecharge(self): taskMgr.remove('rechargeCamera') self.cameraRechargeState = None return def __handleRayInto(self, entry): intoNP = entry.getIntoNodePath() toonNP = intoNP.getParent() for key in base.cr.doId2do.keys(): obj = base.cr.doId2do[key] if obj.__class__.__name__ == 'DistributedToon': if obj.getKey() == toonNP.getKey(): self.__handleToonInFocus(obj) def __handleRayOut(self, entry): intoNP = entry.getIntoNodePath() toonNP = intoNP.getParent() for key in base.cr.doId2do.keys(): obj = base.cr.doId2do[key] if obj.__class__.__name__ == 'DistributedToon': if obj.getKey() == toonNP.getKey(): self.toonToTakePicOf = None self.hasToonInFocus = False if self.cameraFocus.getColorScale() == self.toonInFocusColor: self.cameraFocus.setColorScale(self.toonOutOfFocusColor) return def __handleToonInFocus(self, toon): if not self.hasToonInFocus or self.toonToTakePicOf is not None or self.toonToTakePicOf.doId != toon.doId: self.toonToTakePicOf = toon self.hasToonInFocus = True self.cameraFocus.setColorScale(self.toonInFocusColor) return def start(self): self.fullyChargedSound = base.loadSfx('phase_4/audio/sfx/MG_pairing_match.mp3') self.rechargeSound = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.mp3') self.batteryFrame = DirectFrame(parent=base.a2dBottomRight, pos=(-0.2, 0, 0.1), scale=(0.8, 0, 1)) self.batteryBg = OnscreenImage(image='phase_4/maps/battery_charge_frame.png', parent=self.batteryFrame) self.batteryBg.setTransparency(1) self.batteryBg.setX(0.03) self.batteryBg.setScale(0.17, 0, 0.05) self.batteryBar = DirectWaitBar(value=0, range=5, barColor=(1, 1, 1, 1), relief=None, scale=(0.12, 0.0, 0.3), parent=self.batteryFrame) self.cameraFocus = loader.loadModel('phase_4/models/minigames/photo_game_viewfinder.bam') self.cameraFocus.reparentTo(base.aspect2d) self.focusCollHandler = CollisionHandlerEvent() self.focusCollHandler.setInPattern('%fn-into') self.focusCollHandler.setOutPattern('%fn-out') self.focusCollNode = CollisionNode('mouseRay') self.focusCollNP = base.camera.attachNewNode(self.focusCollNode) self.focusCollNode.setCollideMask(BitMask32(0)) self.focusCollNode.setFromCollideMask(CIGlobals.WallBitmask) self.focusRay = CollisionRay() self.focusRay.setFromLens(base.camNode, 0.0, 0.0) self.focusCollNode.addSolid(self.focusRay) base.cTrav.addCollider(self.focusCollNP, self.focusCollHandler) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, 0.0, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) FirstPerson.start(self) return def reallyStart(self): self.accept('mouseRay-into', self.__handleRayInto) self.accept('mouseRay-out', self.__handleRayOut) self.camFSM.request('recharge') taskMgr.add(self.movementTask, 'movementTask') FirstPerson.reallyStart(self) def end(self): self.camFSM.request('off') taskMgr.remove('movementTask') self.ignore('mouseRay-into') self.ignore('mouseRay-out') FirstPerson.end(self) def reallyEnd(self): self.batteryBar.destroy() self.batteryBar = None self.batteryBg.destroy() self.batteryBg = None self.batteryFrame.destroy() self.batteryFrame = None self.cameraFocus.removeNode() self.cameraFocus = None self.focusCollHandler = None self.focusCollNode = None self.focusCollNP.removeNode() self.focusCollNP = None self.focusRay = None self.hasToonInFocus = None self.toonToTakePicOf = None self.fullyChargedSound = None self.rechargeSound = None self.stopCameraFlash() FirstPerson.reallyEnd(self) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, CIGlobals.ToonJumpForce, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) return def cleanup(self): self.camFSM.requestFinalState() self.camFSM = None FirstPerson.cleanup(self) return