class CogdoFlyingPropeller(CogdoFlyingGatherable): def __init__(self, serialNum, model): CogdoFlyingGatherable.__init__(self, Globals.Level.GatherableTypes.Propeller, serialNum, model, Globals.Gameplay.PropellerCollisionRadius, animate=False) self.activePropellers = [] self.usedPropellers = [] propellers = self._model.findAllMatches('**/propeller*') for prop in propellers: self.activePropellers.append(prop) self.initIntervals() def initIntervals(self): self.animatedPropellerIval = Parallel(name='%s.object-%i-animatePropellerIval' % (self.__class__.__name__, self.serialNum)) for propeller in self.activePropellers: self.animatedPropellerIval.append(LerpHprInterval(propeller, duration=Globals.Level.PropellerSpinDuration, startHpr=Vec3(0.0, 0.0, 0.0), hpr=Vec3(360.0, 0.0, 0.0))) def show(self): self.animatedPropellerIval.loop() CogdoFlyingGatherable.show(self) def hide(self): self.animatedPropellerIval.clearToInitial() CogdoFlyingGatherable.hide(self) def destroy(self): taskMgr.removeTasksMatching('propeller-respawn-*') self.animatedPropellerIval.clearToInitial() del self.animatedPropellerIval CogdoFlyingGatherable.destroy(self) def pickUp(self, toon, elapsedSeconds = 0.0): prop = self.removePropeller() if prop != None: respawnTime = Globals.Gameplay.PropellerRespawnTime if elapsedSeconds < respawnTime: taskMgr.doMethodLater(respawnTime - elapsedSeconds, self.addPropeller, 'propeller-respawn-%i' % self.serialNum, extraArgs=[prop]) else: self.addPropeller(prop) else: self.disable() return def addPropeller(self, prop): if len(self.usedPropellers) > 0: if len(self.activePropellers) == 0: self.enable() self.usedPropellers.remove(prop) prop.show() self.activePropellers.append(prop) self._wasPickedUp = False def removePropeller(self): if len(self.activePropellers) > 0: prop = self.activePropellers.pop() prop.hide() self.usedPropellers.append(prop) if len(self.activePropellers) == 0: self._wasPickedUp = True return prop else: return None def isPropeller(self): if len(self.activePropellers) > 0: return True else: return False
class CogdoFlyingPropeller(CogdoFlyingGatherable): def __init__(self, serialNum, model): CogdoFlyingGatherable.__init__( self, Globals.Level.GatherableTypes.Propeller, serialNum, model, Globals.Gameplay.PropellerCollisionRadius, animate=False) self.activePropellers = [] self.usedPropellers = [] propellers = self._model.findAllMatches('**/propeller*') for prop in propellers: self.activePropellers.append(prop) self.initIntervals() def initIntervals(self): self.animatedPropellerIval = Parallel( name='%s.object-%i-animatePropellerIval' % (self.__class__.__name__, self.serialNum)) for propeller in self.activePropellers: self.animatedPropellerIval.append( LerpHprInterval(propeller, duration=Globals.Level.PropellerSpinDuration, startHpr=Vec3(0.0, 0.0, 0.0), hpr=Vec3(360.0, 0.0, 0.0))) def show(self): self.animatedPropellerIval.loop() CogdoFlyingGatherable.show(self) def hide(self): self.animatedPropellerIval.clearToInitial() CogdoFlyingGatherable.hide(self) def destroy(self): taskMgr.removeTasksMatching('propeller-respawn-*') self.animatedPropellerIval.clearToInitial() del self.animatedPropellerIval CogdoFlyingGatherable.destroy(self) def pickUp(self, toon, elapsedSeconds=0.0): prop = self.removePropeller() if prop != None: respawnTime = Globals.Gameplay.PropellerRespawnTime if elapsedSeconds < respawnTime: taskMgr.doMethodLater(respawnTime - elapsedSeconds, self.addPropeller, 'propeller-respawn-%i' % self.serialNum, extraArgs=[prop]) else: self.addPropeller(prop) else: self.disable() return def addPropeller(self, prop): if len(self.usedPropellers) > 0: if len(self.activePropellers) == 0: self.enable() self.usedPropellers.remove(prop) prop.show() self.activePropellers.append(prop) self._wasPickedUp = False def removePropeller(self): if len(self.activePropellers) > 0: prop = self.activePropellers.pop() prop.hide() self.usedPropellers.append(prop) if len(self.activePropellers) == 0: self._wasPickedUp = True return prop return def isPropeller(self): if len(self.activePropellers) > 0: return True else: return False
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 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('lockOn', self.enterLockOn, self.exitLockOn), State('shoot', self.enterShoot, self.exitShoot) ], 'off', 'off' ) self.fsm.enterInitialState() self.cannon = None self.track = None self.avatar = None self.readyPie = None self.explosion = None self.wallCollNode = None self.eventCollNode = None self.event = None self.piesInFlight = [] def setHealth(self, hp): DistributedAvatar.setHealth(self, hp) if self.getAvatar() == base.localAvatar.doId: 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, 1)) sfx = base.localAvatar.audio3d.loadSfx("phase_3.5/audio/sfx/ENC_cogfall_apart.mp3") base.localAvatar.audio3d.attachSoundToObject(sfx, self) base.playSfx(sfx) 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() def enterOff(self): pass def exitOff(self): pass def makeSplat(self, pos): splat = Actor("phase_3.5/models/props/splat-mod.bam", {"chan": "phase_3.5/models/props/splat-chan.bam"}) splat.setScale(0.5) splat.reparentTo(render) splat.setBillboardPointEye() splat.setColor(VBase4(1, 1, 0, 1)) x, y, z = pos splat.setPos(x, y, z) sfx = base.localAvatar.audio3d.loadSfx("phase_4/audio/sfx/AA_wholepie_only.mp3") base.localAvatar.audio3d.attachSoundToObject(sfx, splat) base.playSfx(sfx) track = Sequence( ActorInterval(splat, "chan"), Func(splat.cleanup), Func(splat.removeNode) ) track.start() def d_makeSplat(self, pos): self.sendUpdate("makeSplat", [pos]) def b_makeSplat(self, pos): self.d_makeSplat(pos) self.makeSplat(pos) def shoot(self, suitId): self.fsm.request('shoot', [suitId]) 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.eventId = random.uniform(0, 100000000) track = Sequence(Parallel(LerpScaleInterval(smoke, 0.5, 3), LerpColorScaleInterval(smoke, 0.5, Vec4(2, 2, 2, 0))), Func(smoke.removeNode)) track.start() self.createAndShootPie() def loadPieInTurret(self): if self.cannon: if self.readyPie: self.readyPie.removeNode() self.readyPie = None pie = loader.loadModel("phase_3.5/models/props/tart.bam") pie.reparentTo(self.cannon.find('**/cannon')) pie.setY(5.2) pie.setHpr(90, -90, 90) self.readyPie = pie def removePieInTurret(self): if self.readyPie: self.readyPie.removeNode() self.readyPie = None def createAndShootPie(self): if not self.readyPie: self.loadPieInTurret() local = 0 if base.localAvatar.doId == self.getAvatar(): local = 1 proj = ProjectilePie(self.uniqueName('pieTurretCollision') + str(self.eventId), self.cannon.find('**/cannon'), self.readyPie, Point3(0, 200, -90), 0.9, 2.5, local, self) self.readyPie = None self.piesInFlight.append(proj) if local: self.acceptOnce(self.uniqueName('pieTurretCollision') + str(self.eventId), self.handlePieCollision) Sequence(Wait(0.25), Func(self.loadPieInTurret)).start() def handlePieCollision(self, entry, proj): x, y, z = proj.pie.getPos(render) self.b_makeSplat([x, y, z]) proj.cleanup() if base.localAvatar.doId == self.getAvatar(): 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: base.localAvatar.sendUpdate('suitHitByPie', [obj.doId, GagGlobals.getIDByName(CIGlobals.WholeCreamPie)]) def exitShoot(self): del self.suit del self.eventId 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 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.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'), ) ) self.track.loop(ts) def _afterShootTrackDone(self): 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'), ) ) self.track.loop() def exitScan(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None def setAvatar(self, avId): self.avatar = avId def getAvatar(self): return self.avatar def makeTurret(self): self.cannon = loader.loadModel("phase_4/models/minigames/toon_cannon.bam") self.cannon.reparentTo(self) self.loadPieInTurret() self.setupWallSphere() if self.getAvatar() == base.localAvatar.doId: self.setupEventSphere() 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 removeTurret(self): self.removeWallSphere() self.removePieInTurret() if self.cannon: self.cannon.removeNode() self.cannon = None def generate(self): DistributedAvatar.generate(self) DistributedSmoothNode.generate(self) def announceGenerate(self): DistributedAvatar.announceGenerate(self) DistributedSmoothNode.announceGenerate(self) self.healthLabel.setScale(1.1) self.makeTurret() def disable(self): self.fsm.requestFinalState() del self.fsm for projs in self.piesInFlight: projs.cleanup() self.piesInFlight = None if self.explosion: self.explosion.removeNode() self.explosion = None self.removeTurret() DistributedSmoothNode.disable(self) DistributedAvatar.disable(self)
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 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.ogg' 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 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()) base.taskMgr.remove(self.uniqueName('DCityCart.drive')) if self.wheelSpinTrack: self.wheelSpinTrack.finish() self.wheelSpinTrack = None if self.moPath: self.moPath.stop() self.moPath = None 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) plans = [] for plan in SuitBank.getSuits(): if plan.getSuitType() != SuitType.B: plans.append(plan) plan = random.choice(plans) self.suitInCar = Suit() self.suitInCar.level = 0 self.suitInCar.generate(plan, Variant.NORMAL) 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.suitInCar.show() self.soundEngineLoop = base.audio3d.loadSfx('phase_6/audio/sfx/KART_Engine_loop_0.ogg') 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.ogg') 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)
class Movement(DirectObject.DirectObject): def __init__(self, parent): self.parent = parent self.hovered_unit_id = None self.hovered_tile = None self.hovered_compass_tile = None self.mouse_node = aspect2d.attachNewNode('mouse_node') self.move_node = aspect2d.attachNewNode('move_node') self.move_outline_node = NodePath('') self.move_np_list = [] self.target_info_node = None self.accept("mouse1", self.mouseLeftClick) self.accept("mouse1-up", self.mouseLeftClickUp) #taskMgr.add(self.rayupdate, 'rayupdate_task') taskMgr.add(self.pickerTask, 'picker_task') taskMgr.add(self.positionTask, 'position_task', sort=2) self.color_scale_parallel = None # Create movement compass nodes self.turn_node = NodePath('turn_node') self.turn_node.setTag('show', '0') self.turn_np_list = [] for i in xrange(9): text = TextNode('node name') text.setAlign(TextNode.ACenter) if i == 0: text.setText('NW') key = utils.HEADING_NW elif i == 1: text.setText('N') key = utils.HEADING_N elif i == 2: text.setText('NE') key = utils.HEADING_NE elif i == 3: text.setText('W') key = utils.HEADING_W elif i == 4: text.setText('E') key = utils.HEADING_E elif i == 5: text.setText('SW') key = utils.HEADING_SW elif i == 6: text.setText('S') key = utils.HEADING_S elif i == 7: text.setText('SE') key = utils.HEADING_SE elif i == 8: text.setText('X') key = utils.HEADING_NONE textNodePath = self.turn_node.attachNewNode(text) textNodePath.setColor(1, 1, 1) textNodePath.setScale(0.06) textNodePath.setTag('key', str(key)) self.turn_np_list.append(textNodePath) def calcUnitAvailMove(self, unit_id): """Displays visual indicator of tiles which are in movement range of the selected unit.""" # First delete old movement list for c in self.move_np_list: c.removeNode() self.move_np_list = [] # Start calculation of new list unit = self.parent.local_engine.units[unit_id] if self.parent.turn_player != self.parent.player_id: return if unit: unit['move_dict'] = getMoveDict(unit, self.parent.local_engine.level, self.parent.local_engine.units) self.parent.local_engine.units[unit_id]['move_dict'] = unit[ 'move_dict'] move_dict = unit['move_dict'] for tile in move_dict: text = TextNode('node name') text.setText("%s" % move_dict[tile]) text.setAlign(TextNode.ACenter) textNodePath = self.move_node.attachNewNode(text) textNodePath.setColor(1, 1, 1) textNodePath.setScale(0.06) textNodePath.setPythonTag('pos', tile) pos2d = utils.pointCoordIn2d( Point3(utils.TILE_SIZE * (tile[0] + 0.5), utils.TILE_SIZE * (tile[1] + 0.5), utils.GROUND_LEVEL)) textNodePath.setPos(pos2d) self.move_np_list.append(textNodePath) def showUnitAvailMove(self): self.move_node.reparentTo(aspect2d) self.hovered_tile = None #self.drawMoveOutline(self.calcMoveOutline(move_dict, self.parent.local_engine.units[unit_id]['pos'])) def hideUnitAvailMove(self): self.move_node.detachNode() """ def calcMoveOutline(self, move_dict, pos): outline = {} for tile in move_dict: dir = [] if not (tile[0]-1, tile[1]) in move_dict and (tile[0]-1, tile[1]) != pos: dir.append('W') if not (tile[0], tile[1]-1) in move_dict and (tile[0], tile[1]-1) != pos: dir.append('S') if not (tile[0]+1, tile[1]) in move_dict and (tile[0]+1, tile[1]) != pos: dir.append('E') if not (tile[0], tile[1]+1) in move_dict and (tile[0], tile[1]+1) != pos: dir.append('N') if dir != []: outline[tile] = dir return outline def drawMoveOutline(self, outline): self.move_outline_node.removeNode() zpos = utils.GROUND_LEVEL + 0.01 off = 0.1 segs = LineSegs() segs.setThickness(3) segs.setColor(Vec4(0.686,1,0.992,1)) for tile in outline: for dir in outline[tile]: if dir == 'N': d1 = 0 d2 = 0 if (tile[0]+1, tile[1]) in outline and 'N' in outline[(tile[0]+1, tile[1])]: d2 = off elif (tile[0]+1, tile[1]+1) in outline: d2 = 2*off if (tile[0]-1, tile[1]) in outline and 'N' in outline[(tile[0]-1, tile[1])]: d1 = off elif (tile[0]-1, tile[1]+1) in outline: d1 = 2*off segs.moveTo(tile[0]+off-d1, tile[1]+1-off, zpos) segs.drawTo(tile[0]+1-off+d2, tile[1]+1-off, zpos) elif dir == 'S': d1 = 0 d2 = 0 if (tile[0]+1, tile[1]) in outline and 'S' in outline[(tile[0]+1, tile[1])]: d2 = off elif (tile[0]+1, tile[1]-1) in outline: d2 = 2*off if (tile[0]-1, tile[1]) in outline and 'S' in outline[(tile[0]-1, tile[1])]: d1 = off elif (tile[0]-1, tile[1]-1) in outline: d1 = 2*off segs.moveTo(tile[0]+off-d1, tile[1]+off, zpos) segs.drawTo(tile[0]+1-off+d2, tile[1]+off, zpos) elif dir == 'W': d1 = 0 d2 = 0 if (tile[0], tile[1]+1) in outline and 'W' in outline[(tile[0], tile[1]+1)]: d2 = off elif (tile[0]-1, tile[1]+1) in outline: d2 = 2*off if (tile[0], tile[1]-1) in outline and 'W' in outline[(tile[0], tile[1]-1)]: d1 = off elif (tile[0]-1, tile[1]-1) in outline: d1 = 2*off segs.moveTo(tile[0]+off, tile[1]+off-d1, zpos) segs.drawTo(tile[0]+off, tile[1]+1-off+d2, zpos) elif dir == 'E': d1 = 0 d2 = 0 if (tile[0], tile[1]+1) in outline and 'E' in outline[(tile[0], tile[1]+1)]: d2 = off elif (tile[0]+1, tile[1]+1) in outline: d2 = 2*off if (tile[0], tile[1]-1) in outline and 'E' in outline[(tile[0], tile[1]-1)]: d1 = off elif (tile[0]+1, tile[1]-1) in outline: d1 = 2*off segs.moveTo(tile[0]+1-off, tile[1]+off-d1, zpos) segs.drawTo(tile[0]+1-off, tile[1]+1-off+d2, zpos) self.move_outline_node = render.attachNewNode(segs.create()) self.move_outline_node.setBin("fixed", 40) #self.move_outline_node.setDepthTest(False) #self.move_outline_node.setDepthWrite(False) self.move_outline_node.setLightOff() """ def showMoveCompass(self, dest): # Calculate postion of compass nodes based on destination tile for i in self.turn_np_list: i.setPythonTag('pos', utils.getHeadingTile(i.getTag('key'), dest)) # Show compass nodes self.turn_node.reparentTo(aspect2d) self.turn_node.setPythonTag('pos', dest) self.turn_node.setTag('show', '1') # Hide move nodes self.move_node.detachNode() def hideMoveCompass(self): # Hide compass nodes self.turn_node.detachNode() self.turn_node.setTag('show', '0') if self.hovered_compass_tile != None: self.hovered_compass_tile.setColor(1, 1, 1) self.hovered_compass_tile.setScale(0.05) self.color_scale_parallel.pause() self.hovered_compass_tile = None def mouseLeftClick(self): if self.parent.interface.hovered_gui != None: return if self.hovered_unit_id != None: unit_id = int(self.hovered_unit_id) pickedCoord = self.parent.local_engine.getCoordsByUnit(unit_id) # Player can only select his own units if self.parent.local_engine.isThisMyUnit(unit_id): if unit_id != self.parent.sel_unit_id: self.parent.selectUnit(unit_id) else: # Remember movement tile so we can send orientation message when mouse is depressed # Do this only if it is our turn if self.parent.player_id == self.parent.turn_player: self.unit_move_destination = pickedCoord self.showMoveCompass(self.unit_move_destination) elif self.parent.local_engine.isThisEnemyUnit(unit_id): if self.parent.sel_unit_id != None and self.parent.player_id == self.parent.turn_player: self.parent.render_manager.unit_renderer_dict[ self.parent. sel_unit_id].target_unit = self.parent.render_manager.unit_renderer_dict[ unit_id] if self.parent._anim_in_process == False: ClientMsg.shoot(self.parent.sel_unit_id, unit_id) elif self.hovered_tile != None: if self.parent.sel_unit_id != None and self.parent.player_id == self.parent.turn_player: # Remember movement tile so we can send movement message when mouse is depressed # Do this only if it is our turn move_coord = self.hovered_tile.getPythonTag('pos') if self.parent.local_engine.units[self.parent.sel_unit_id][ 'move_dict'].has_key(move_coord): self.unit_move_destination = move_coord self.showMoveCompass(self.unit_move_destination) def mouseLeftClickUp(self): """Handles left mouse click actions when mouse button is depressed. Used for unit movement. """ o = None if self.hovered_compass_tile != None: x = self.turn_node.getPythonTag('pos')[0] y = self.turn_node.getPythonTag('pos')[1] orientation = int(self.hovered_compass_tile.getTag('key')) if orientation == utils.HEADING_NW: o = Point2(x - 1, y + 1) elif orientation == utils.HEADING_N: o = Point2(x, y + 1) elif orientation == utils.HEADING_NE: o = Point2(x + 1, y + 1) elif orientation == utils.HEADING_W: o = Point2(x - 1, y) elif orientation == utils.HEADING_E: o = Point2(x + 1, y) elif orientation == utils.HEADING_SW: o = Point2(x - 1, y - 1) elif orientation == utils.HEADING_S: o = Point2(x, y - 1) elif orientation == utils.HEADING_SE: o = Point2(x + 1, y - 1) else: o = None self.hideMoveCompass() if o != None: ClientMsg.move(self.parent.sel_unit_id, (x, y), (o.x, o.y)) def positionTask(self, task): # If turn node is displayed, you have to cancel turning or turn to be able to pick another unit or another tile to move to if self.turn_node.getTag('show') == '1': for tile in self.turn_np_list: pos = Point3( utils.TILE_SIZE * (tile.getPythonTag('pos')[0] + 0.5), utils.TILE_SIZE * (tile.getPythonTag('pos')[1]) + 0.5, utils.GROUND_LEVEL) pos2d = utils.pointCoordIn2d(pos) tile.setPos(pos2d) else: for unit in self.parent.render_manager.unit_renderer_dict.itervalues( ): p = utils.nodeCoordIn2d(unit.model) unit.node_2d.setPos(p) for tile in self.move_np_list: pos = Point3( utils.TILE_SIZE * (tile.getPythonTag('pos')[0] + 0.5), utils.TILE_SIZE * (tile.getPythonTag('pos')[1] + 0.5), utils.GROUND_LEVEL) pos2d = utils.pointCoordIn2d(pos) tile.setPos(pos2d) return task.cont def pickerTask(self, task): if self.parent._anim_in_process: self.hovered_unit_id = None self.hovered_tile = None self.hovered_compass_tile = None return task.cont if self.parent.interface.hovered_gui != None: if self.hovered_unit_id != None: self.parent.render_manager.unit_marker_renderer.unmarkHovered( self.hovered_unit_id) self.hovered_unit_id = None if self.hovered_tile != None and not self.hovered_tile.isEmpty(): self.hovered_tile.setColor(1, 1, 1) self.hovered_tile.setScale(0.05) self.color_scale_parallel.pause() if self.hovered_compass_tile != None and not self.hovered_compass_tile.isEmpty( ): self.hovered_compass_tile.setColor(1, 1, 1) self.hovered_compass_tile.setScale(0.05) self.color_scale_parallel.pause() return task.cont min_distance = 0.5 min_unit_id = None min_tile = None min_compass_tile = None if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() r2d = Point3(mpos.getX(), 0, mpos.getY()) a2d = aspect2d.getRelativePoint(render2d, r2d) self.mouse_node.setPos(a2d) # At the end of all this we have: # - min_distance to a unit or a movement node, IF this distance is lower than 0.5 which is set at the beginning # - min_unit_id - ID of unit which is closest to the mouse, or None if there is a movement tile closer, or if everything is further than 0.5 # - min_tile - nodepath of the movement tile closest to the mouse, or None if there is a unit closer, or if evertythin is further than 0.5 if self.turn_node.getTag('show') == '1': # Get 2d coordinates for every compass node for tile in self.turn_np_list: # We cannot do nodepath.getDistance() because tiles are reparented to self.turn_node and are in different coord space than mouse node # So we do simple vector math to get distance d = Vec3(self.mouse_node.getPos() - tile.getPos()).length() if d < min_distance: min_distance = d min_unit_id = None min_tile = None min_compass_tile = tile else: # Get 2d coordinates of all units for unit_id in self.parent.render_manager.unit_renderer_dict: unit = self.parent.render_manager.unit_renderer_dict[ unit_id] if self.parent.local_engine.isThisMyUnit(unit_id): # Calculate distance between every friendly unit and mouse cursor and remember closest unit d = self.mouse_node.getDistance(unit.node_2d) if d < min_distance: min_distance = d min_unit_id = unit_id else: # Calculate distance between every enemy unit and mouse cursor and remember closest unit d = self.mouse_node.getDistance(unit.node_2d) # To target enemy unit, distance has to be even smaller than needed for regular selection/movement if d < min_distance and d < 0.1: min_distance = d min_unit_id = unit_id # Get 2d coordinates for every movement node of the selected unit for tile in self.move_np_list: # We cannot do nodepath.getDistance() because tiles are reparented to self.move_node and are in different coord space than mouse node # So we do simple vector math to get distance d = Vec3(self.mouse_node.getPos() - tile.getPos()).length() if d < min_distance: min_distance = d min_unit_id = None min_tile = tile # If a unit is the closest to the mouse: # - hide movement nodes (Incubation style!) # - unmark last hovered unit # - unmark last hovered tile # - mark new hovered unit # TODO: ogs: potencijalna optimizacija da se provjeri da li je self.hovered_unit_id = min_unit_id, tada ne treba unmark+mark if min_compass_tile != None: if self.hovered_tile != None and not self.hovered_tile.isEmpty(): self.hovered_tile.setColor(1, 1, 1) self.hovered_tile.setScale(0.05) self.color_scale_parallel.pause() self.hovered_tile = None if min_compass_tile != self.hovered_compass_tile: if self.hovered_compass_tile != None and not self.hovered_compass_tile.isEmpty( ): self.hovered_compass_tile.setColor(1, 1, 1) self.hovered_compass_tile.setScale(0.05) self.color_scale_parallel.pause() min_compass_tile.setColor(1, 0, 0) s1 = Sequence( LerpColorInterval(min_compass_tile, 0.5, (1, 1, 0, 1)), LerpColorInterval(min_compass_tile, 0.5, (1, 0, 0, 1))) s2 = Sequence(LerpScaleInterval(min_compass_tile, 0.5, (0.1)), LerpScaleInterval(min_compass_tile, 0.5, (0.05))) self.color_scale_parallel = Parallel(s1, s2) self.color_scale_parallel.loop() self.hovered_compass_tile = min_compass_tile elif min_unit_id != None: self.move_node.detachNode() if min_unit_id != self.hovered_unit_id and self.hovered_unit_id != None: if self.parent.render_manager.unit_renderer_dict.has_key( int(self.hovered_unit_id)): self.parent.render_manager.unit_marker_renderer.unmarkHovered( self.hovered_unit_id) self.parent.render_manager.unit_marker_renderer.markHovered( min_unit_id) if self.hovered_tile != None and not self.hovered_tile.isEmpty(): self.hovered_tile.setColor(1, 1, 1) self.hovered_tile.setScale(0.05) self.color_scale_parallel.pause() self.hovered_tile = None self.hovered_unit_id = min_unit_id # If a movement tile is closest to the mouse: # - unmark last hovered unit # - unmark last marked tile # - show movement nodes (Incubation style!) # - mark new hovered tile elif min_tile != None: if self.hovered_unit_id != None: if self.parent.render_manager.unit_renderer_dict.has_key( int(self.hovered_unit_id)): self.parent.render_manager.unit_marker_renderer.unmarkHovered( self.hovered_unit_id) self.hovered_unit_id = None if min_tile != self.hovered_tile: self.move_node.reparentTo(aspect2d) if self.hovered_tile != None and not self.hovered_tile.isEmpty( ): self.hovered_tile.setColor(1, 1, 1) self.hovered_tile.setScale(0.05) self.color_scale_parallel.pause() min_tile.setColor(1, 0, 0) s1 = Sequence(LerpColorInterval(min_tile, 0.5, (1, 1, 0, 1)), LerpColorInterval(min_tile, 0.5, (1, 0, 0, 1))) s2 = Sequence(LerpScaleInterval(min_tile, 0.5, (0.1)), LerpScaleInterval(min_tile, 0.5, (0.05))) self.color_scale_parallel = Parallel(s1, s2) self.color_scale_parallel.loop() self.hovered_tile = min_tile # If neither any of the units nor any of the movement tiles is closer than 0.5: # - unmark last hovered unit # - unmark last hovered tile else: if self.hovered_unit_id != None: if self.parent.render_manager.unit_renderer_dict.has_key( int(self.hovered_unit_id)): self.parent.render_manager.unit_marker_renderer.unmarkHovered( self.hovered_unit_id) self.hovered_unit_id = None if self.hovered_tile != None and not self.hovered_tile.isEmpty(): self.hovered_tile.setColor(1, 1, 1) self.hovered_tile.setScale(0.05) self.color_scale_parallel.pause() self.hovered_tile = None if self.hovered_compass_tile != None and not self.hovered_compass_tile.isEmpty( ): self.hovered_compass_tile.setColor(1, 1, 1) self.hovered_compass_tile.setScale(0.05) self.color_scale_parallel.pause() self.hovered_compass_tile = None return task.cont