def enterDie(self, ts=0):
        self.show()
        self.generateCog(isLose=1)
        self.nametag.clearChatText()
        self.deleteNameTag()
        deathSound = base.audio3d.loadSfx(
            "phase_3.5/audio/sfx/Cog_Death_Full.ogg")
        base.audio3d.attachSoundToObject(deathSound, self)
        trackName = self.uniqueName('enterDie')

        smallGears = ParticleLoader.loadParticleEffect(
            'phase_3.5/etc/gearExplosionSmall.ptf')
        smallGears.getParticlesNamed('particles-1').setPoolSize(30)

        singleGear = ParticleLoader.loadParticleEffect(
            'phase_3.5/etc/gearExplosion.ptf')
        singleGear.getParticlesNamed('particles-1').setPoolSize(1)

        smallGearExplosion = ParticleLoader.loadParticleEffect(
            'phase_3.5/etc/gearExplosion.ptf')
        smallGearExplosion.getParticlesNamed('particles-1').setPoolSize(10)

        bigGearExplosion = ParticleLoader.loadParticleEffect(
            'phase_3.5/etc/gearExplosionBig.ptf')
        bigGearExplosion.getParticlesNamed('particles-1').setPoolSize(30)

        smallGears.setDepthWrite(False)
        singleGear.setDepthWrite(False)
        smallGearExplosion.setDepthWrite(False)
        bigGearExplosion.setDepthWrite(False)

        self.smallGears = smallGears
        self.smallGears.setPos(self.find('**/joint_head').getPos() + (0, 0, 2))
        self.singleGear = singleGear
        self.smallGearExp = smallGearExplosion
        self.bigGearExp = bigGearExplosion

        gearTrack = Sequence(Wait(0.7), Func(self.doSingleGear), Wait(1.5),
                             Func(self.doSmallGears), Wait(3.0),
                             Func(self.doBigExp))
        self.suitTrack = Parallel(Sequence(
            Wait(0.8),
            SoundInterval(deathSound,
                          node=self,
                          duration=deathSound.length() / 2)),
                                  Sequence(Wait(0.7), Func(self.doSingleGear),
                                           Wait(4.3), Func(self.suitExplode),
                                           Wait(1.0),
                                           Func(self.disableBodyCollisions),
                                           Func(self.__cleanupExplosion)),
                                  gearTrack,
                                  Sequence(
                                      ActorInterval(self, 'lose', duration=6),
                                      Func(self.getGeomNode().hide)),
                                  name=trackName)
        self.suitTrack.setDoneEvent(self.suitTrack.getName())
        self.acceptOnce(self.suitTrack.getName(), self.exitDie)
        self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, trackName)
        self.suitTrack.start(ts)
        del deathSound
Пример #2
0
    def doAttack(self, particlePaths, track_name, particleCollId, animation_name, delayUntilRelease, animationSpeed = 1, handObjPath = None, handObjParent = None, startRightAway = True, ts = 0):
        for path in particlePaths:
            particle = ParticleLoader.loadParticleEffect(path)
            self.particles.append(particle)

        sphere = CollisionSphere(0, 0, 0, 1)
        sphere.setTangible(0)
        node = CollisionNode(particleCollId)
        node.addSolid(sphere)
        node.setCollideMask(CIGlobals.WallBitmask)
        self.targetX = self.attacksClass.target.getX(render)
        self.targetY = self.attacksClass.target.getY(render)
        self.targetZ = self.attacksClass.target.getZ(render)
        if len(self.particles) == 1:
            self.shootOutCollNP = self.particles[0].attachNewNode(node)
        else:
            self.shootOutCollNP = self.suit.attachNewNode(node)
        if handObjPath and handObjParent:
            self.handObj = loader.loadModel(handObjPath)
            self.handObj.reparentTo(handObjParent)
        self.suit.setPlayRate(animationSpeed, animation_name)
        self.suit.play(animation_name)
        if hasattr(self.suit, 'uniqueName'):
            track_name = self.suit.uniqueName(track_name)
            particleCollId = self.suit.uniqueName(particleCollId)
        self.suitTrack = Sequence(name=track_name)
        self.suitTrack.append(Wait(delayUntilRelease))
        self.suitTrack.append(Func(self.releaseAttack))
        self.suitTrack.append(Wait(self.particleIvalDur))
        self.suitTrack.setDoneEvent(self.suitTrack.getName())
        self.acceptOnce(self.suitTrack.getDoneEvent(), self.finishedAttack)
        if startRightAway:
            self.suitTrack.start(ts)
    def doAttack(self, particlePaths, track_name, particleCollId, animation_name, delayUntilRelease, animationSpeed=1, handObjPath=None, handObjParent=None, startRightAway=True, ts=0):
        for path in particlePaths:
            particle = ParticleLoader.loadParticleEffect(path)
            self.particles.append(particle)

        sphere = CollisionSphere(0, 0, 0, 1)
        sphere.setTangible(0)
        node = CollisionNode(particleCollId)
        node.addSolid(sphere)
        node.setCollideMask(CIGlobals.WallBitmask)
        self.targetX = self.attacksClass.target.getX(render)
        self.targetY = self.attacksClass.target.getY(render)
        self.targetZ = self.attacksClass.target.getZ(render)
        if len(self.particles) == 1:
            self.shootOutCollNP = self.particles[0].attachNewNode(node)
        else:
            self.shootOutCollNP = self.suit.attachNewNode(node)
        if handObjPath and handObjParent:
            self.handObj = loader.loadModel(handObjPath)
            self.handObj.reparentTo(handObjParent)
        self.suit.setPlayRate(animationSpeed, animation_name)
        self.suit.play(animation_name)
        if hasattr(self.suit, 'uniqueName'):
            track_name = self.suit.uniqueName(track_name)
            particleCollId = self.suit.uniqueName(particleCollId)
        self.suitTrack = Sequence(name=track_name)
        self.suitTrack.append(Wait(delayUntilRelease))
        self.suitTrack.append(Func(self.releaseAttack))
        self.suitTrack.append(Wait(self.particleIvalDur))
        self.suitTrack.setDoneEvent(self.suitTrack.getName())
        self.acceptOnce(self.suitTrack.getDoneEvent(), self.finishedAttack)
        if startRightAway:
            self.suitTrack.start(ts)
Пример #4
0
 def load(self):
     SafeZoneLoader.load(self)
     self.soundRain = base.loadSfx('phase_14/audio/sfx/rain_ambient.mp3')
     self.rain = ParticleLoader.loadParticleEffect('phase_14/etc/rain.ptf')
     self.rain.setPos(0, 0, 5)
     self.rainRender = self.geom.attachNewNode('snowRender')
     self.rainRender.setDepthWrite(0)
     self.rainRender.setBin('fixed', 1)
Пример #5
0
 def load(self):
     SafeZoneLoader.load(self)
     self.soundRain = base.loadSfx('phase_14/audio/sfx/rain_ambient.ogg')
     self.rain = ParticleLoader.loadParticleEffect('phase_14/etc/rain.ptf')
     self.rain.setPos(0, 0, 5)
     self.rainRender = self.geom.attachNewNode('snowRender')
     self.rainRender.setDepthWrite(0)
     self.rainRender.setBin('fixed', 1)
    def enterDie(self, ts = 0):
        self.show()
        self.generateLoserSuit()
        self.clearChat()
        self.state = "dead"
        self.play("lose")
        deathSound = base.audio3d.loadSfx("phase_3.5/audio/sfx/Cog_Death_Full.ogg")
        base.audio3d.attachSoundToObject(deathSound, self)
        trackName = self.uniqueName('enterDie')

        smallGears = ParticleLoader.loadParticleEffect('phase_3.5/etc/gearExplosionSmall.ptf')
        smallGears.getParticlesNamed('particles-1').setPoolSize(30)

        singleGear = ParticleLoader.loadParticleEffect('phase_3.5/etc/gearExplosion.ptf')
        singleGear.getParticlesNamed('particles-1').setPoolSize(1)

        smallGearExplosion = ParticleLoader.loadParticleEffect('phase_3.5/etc/gearExplosion.ptf')
        smallGearExplosion.getParticlesNamed('particles-1').setPoolSize(10)

        bigGearExplosion = ParticleLoader.loadParticleEffect('phase_3.5/etc/gearExplosionBig.ptf')
        bigGearExplosion.getParticlesNamed('particles-1').setPoolSize(30)

        smallGears.setDepthWrite(False)
        singleGear.setDepthWrite(False)
        smallGearExplosion.setDepthWrite(False)
        bigGearExplosion.setDepthWrite(False)

        self.smallGears = smallGears
        self.smallGears.setPos(self.find('**/joint_head').getPos() + (0,0, 2))
        self.singleGear = singleGear
        self.smallGearExp = smallGearExplosion
        self.bigGearExp = bigGearExplosion

        gearTrack = Sequence(Wait(0.7), Func(self.doSingleGear), Wait(1.5), Func(self.doSmallGears), Wait(3.0), Func(self.doBigExp))
        self.suitTrack = Parallel(Sequence(Wait(0.7), Func(self.doSingleGear), Wait(4.3),
                Func(self.suitExplode), Wait(1.0), Func(self.delSuit)), gearTrack, name = trackName)
        self.suitTrack.setDoneEvent(self.suitTrack.getName())
        Sequence(Wait(0.8), SoundInterval(deathSound)).start()
        self.acceptOnce(self.suitTrack.getName(), self.exitDie)
        if "Distributed" in self.__class__.__name__:
            self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, trackName)
        self.suitTrack.start(ts)
        del deathSound
Пример #7
0
 def load(self):
     SafeZoneLoader.SafeZoneLoader.load(self)
     self.snow = ParticleLoader.loadParticleEffect('phase_8/etc/snowdisk.ptf')
     self.snow.setPos(0, 0, 5)
     self.snowRender = self.geom.attachNewNode('snowRender')
     self.snowRender.setDepthWrite(0)
     self.snowRender.setBin('fixed', 1)
     hq = self.geom.find('**/*toon_landmark_hqBR*')
     hq.find('**/doorFrameHoleLeft_0').stash()
     hq.find('**/doorFrameHoleRight_0').stash()
     hq.find('**/doorFrameHoleLeft_1').stash()
     hq.find('**/doorFrameHoleRight_1').stash()
Пример #8
0
	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))
Пример #9
0
 def load(self):
     SafeZoneLoader.SafeZoneLoader.load(self)
     self.snow = ParticleLoader.loadParticleEffect('phase_8/etc/snowdisk.ptf')
     self.snow.setPos(0, 0, 5)
     self.snowRender = self.geom.attachNewNode('snowRender')
     self.snowRender.setDepthWrite(0)
     self.snowRender.setBin('fixed', 1)
     hq = self.geom.find('**/*toon_landmark_hqBR*')
     hq.find('**/doorFrameHoleLeft_0').stash()
     hq.find('**/doorFrameHoleRight_0').stash()
     hq.find('**/doorFrameHoleLeft_1').stash()
     hq.find('**/doorFrameHoleRight_1').stash()
Пример #10
0
 def load(self):
     Place.Place.load(self)
     self.parentFSM.getStateNamed('playground').addChild(self.fsm)
     if base.cr.holidayManager.getHoliday() == HolidayType.CHRISTMAS:
         self.particles = ParticleLoader.loadParticleEffect('phase_8/etc/snowdisk.ptf')
         self.particles.setPos(0, 0, 5)
         self.particlesRender = self.loader.geom.attachNewNode('snowRender')
         self.particlesRender.setDepthWrite(0)
         self.particlesRender.setBin('fixed', 1)
         self.particles.start(parent=camera, renderParent=self.particlesRender)
         self.fog = Fog('snowFog')
         self.fog.setColor(0.486, 0.784, 1)
         self.fog.setExpDensity(0.003)
         base.render.setFog(self.fog)
    def createWorld(self):
        self.deleteWorld()

        self.sky = loader.loadModel("phase_3.5/models/props/BR_sky.bam")
        self.sky.reparentTo(render)
        self.sky.setZ(-40)
        self.sky.setFogOff()

        self.arena = loader.loadModel("phase_4/models/minigames/dodgeball_arena.egg")
        self.arena.reparentTo(render)
        self.arena.setScale(0.75)
        self.arena.find('**/team_divider').setBin('ground', 18)
        self.arena.find('**/floor').setBin('ground', 18)
        self.arena.find('**/team_divider_coll').setCollideMask(CIGlobals.FloorBitmask)

        for data in DistributedDodgeballGame.TreeData:
            code = data[0]
            pos = data[1]
            tree = self.__getSnowTree(code)
            tree.reparentTo(self.arena)
            tree.setPos(pos)
            self.trees.append(tree)

        for i in xrange(len(DistributedDodgeballGame.SnowballData)):
            snowdata = DistributedDodgeballGame.SnowballData[i]
            snowball = Snowball(self, i)
            snowball.load()
            snowball.reparentTo(render)
            snowball.setPos(snowdata)
            self.snowballs.append(snowball)

        self.snow = ParticleLoader.loadParticleEffect('phase_8/etc/snowdisk.ptf')
        self.snow.setPos(0, 0, 5)
        self.snowRender = self.arena.attachNewNode('snowRender')
        self.snowRender.setDepthWrite(0)
        self.snowRender.setBin('fixed', 1)
        self.snow.start(camera, self.snowRender)

        self.fog = Fog('snowFog')
        self.fog.setColor(0.486, 0.784, 1)
        self.fog.setExpDensity(0.003)
        render.setFog(self.fog)
Пример #12
0
 def loadAttack(self):
     self.pen = loader.loadModel('phase_5/models/props/pen.bam')
     self.pen.reparentTo(self.suit.find('**/joint_Rhold'))
     self.sprayParticle = ParticleLoader.loadParticleEffect('phase_5/etc/penSpill.ptf')
     self.spray = loader.loadModel('phase_3.5/models/props/spray.bam')
     self.spray.setColor(VBase4(0, 0, 0, 1))
     self.splat = Actor('phase_3.5/models/props/splat-mod.bam', {'chan': 'phase_3.5/models/props/splat-chan.bam'})
     self.splat.setColor(VBase4(0, 0, 0, 1))
     self.sprayScaleIval = LerpScaleInterval(self.spray, duration=0.3, scale=(1, 20, 1), startScale=(1, 1, 1))
     sphere = CollisionSphere(0, 0, 0, 0.5)
     sphere.setTangible(0)
     if hasattr(self.suit, 'uniqueName'):
         collName = self.suit.uniqueName('fountainPenCollNode')
     else:
         collName = 'fountainPenCollNode'
     collNode = CollisionNode(collName)
     collNode.addSolid(sphere)
     collNode.setCollideMask(CIGlobals.WallBitmask)
     self.wsnp = self.spray.attachNewNode(collNode)
     self.wsnp.setY(1)
 def loadAttack(self):
     self.pen = loader.loadModel('phase_5/models/props/pen.bam')
     self.pen.reparentTo(self.suit.find('**/joint_Rhold'))
     self.sprayParticle = ParticleLoader.loadParticleEffect('phase_5/etc/penSpill.ptf')
     self.spray = loader.loadModel('phase_3.5/models/props/spray.bam')
     self.spray.setColor(VBase4(0, 0, 0, 1))
     self.splat = Actor('phase_3.5/models/props/splat-mod.bam', {'chan': 'phase_3.5/models/props/splat-chan.bam'})
     self.splat.setColor(VBase4(0, 0, 0, 1))
     self.sprayScaleIval = LerpScaleInterval(self.spray, duration=0.3, scale=(1,
                                                                              20,
                                                                              1), startScale=(1,
                                                                                              1,
                                                                                              1))
     sphere = CollisionSphere(0, 0, 0, 0.5)
     sphere.setTangible(0)
     if hasattr(self.suit, 'uniqueName'):
         collName = self.suit.uniqueName('fountainPenCollNode')
     else:
         collName = 'fountainPenCollNode'
     collNode = CollisionNode(collName)
     collNode.addSolid(sphere)
     collNode.setCollideMask(CIGlobals.WallBitmask)
     self.wsnp = self.spray.attachNewNode(collNode)
     self.wsnp.setY(1)
Пример #14
0
	def smallDeathParticles(self):
		self.smallExp = ParticleLoader.loadParticleEffect("phase_3.5/etc/gearExplosionSmall.ptf")
		self.smallExp.start(self.loserSuit)
    np = render.attachNewNode(node)
    np.setScale(scale)
    return np

for data in tree_data:
	code = data[0]
	pos = data[1]
	tree = getSnowTree(code)
	tree.reparentTo(arena)
	tree.setPos(pos)
	trees.append(tree)

music = base.loadMusic('phase_4/audio/bgm/MG_Dodgeball.mp3')
base.playMusic(music, 1, volume = 0.8)

snow = ParticleLoader.loadParticleEffect('phase_8/etc/snowdisk.ptf')
snow.setPos(0, 0, 5)
snowRender = arena.attachNewNode('snowRender')
snowRender.setDepthWrite(0)
snowRender.setBin('fixed', 1)
snow.start(camera, snowRender)

fog = Fog('snowFog')
fog.setColor(0.486, 0.784, 1)
fog.setExpDensity(0.003)
render.setFog(fog)

#bSign = getBigText("B", (0, 0, 1, 1), 1)
#rSign = getBigText("R", (1, 0, 0, 1), 1)

#bSign.setPosHpr(-5.11, 66.98, 11.53, 0, 338.96, 0)
Пример #16
0
    def load(self):
        base.cr.renderFrame()
        base.camLens.setMinFov(CIGlobals.DefaultCameraFov / (4./3.))

        self.__setupStageToon()
        holidayMgr = base.cr.holidayManager

        self.props = []
        self.world = loader.loadModel('phase_9/models/cogHQ/SellbotHQExterior.bam')
        self.world.reparentTo(base.render)
        self.world.setPos(0, 227.09, -25.36)
        self.sky = loader.loadModel('phase_9/models/cogHQ/cog_sky.bam')
        self.sky.setScale(1)
        self.sky.reparentTo(base.render)
        self.sky.find('**/InnerGroup').removeNode()
        self.fog = Fog('charSelectFog')
        self.fog.setColor(0.2, 0.2, 0.2)
        self.fog.setExpDensity(0.003)
        base.render.setFog(self.fog)
        
        # Let's fix the flickering doors.
        doors = self.world.find('**/doors').getChildren()
        
        for door in doors:
            for frameHole in door.findAllMatches('**/doorFrameHole*'): frameHole.removeNode()

        if holidayMgr.getHoliday() == HolidayType.CHRISTMAS:
            piles = {
                'half' : {'pos' : (57.28, 86.47, -25.00), 'hpr' : (46.79, 0, 0)},
                'full' : {'pos' : (71.23, 85.2, -25.00), 'hpr' : (290.82, 0, 0)},
                'half_2' : {'pos' : (-15, 128.69, -25), 'hpr' : (60.26, 0, 0)}
            }

            for pileType, info in piles.items():
                if '_' in pileType:
                    pileType = pileType[:-2]
                pile = loader.loadModel('phase_8/models/props/snow_pile_%s.bam' % (pileType))
                pile.reparentTo(render)
                pile.setPos(info['pos'])
                pile.setHpr(info['hpr'])
                self.props.append(pile)

            self.world.find('**/TopRocks').removeNode()

            snowTxt = loader.loadTexture('winter/maps/sbhq_snow.png')
            self.world.find('**/Ground').setTexture(snowTxt, 1)

            self.particles = ParticleLoader.loadParticleEffect('phase_8/etc/snowdisk.ptf')
            self.particles.setPos(0, 0, 5)
            self.particlesRender = self.world.attachNewNode('snowRender')
            self.particlesRender.setDepthWrite(0)
            self.particlesRender.setBin('fixed', 1)
            self.particles.start(parent = camera, renderParent = self.particlesRender)
            self.fog.setColor(0.486, 0.784, 1)
            self.fog.setExpDensity(0.006)
            base.render.setFog(self.fog)


        self.title = DirectLabel(text=self.TITLE, text_font=CIGlobals.getMickeyFont(), text_fg=(1, 0.9, 0.1, 1),
                                relief=None, text_scale=0.13, pos=(0, 0, 0.82))
        self.charNameLabel = OnscreenText(text = "", font = CIGlobals.getMickeyFont(),
                                        pos = (-0.25, 0.5, 0), fg = (1, 0.9, 0.1, 1.0))
        self.charNameLabel.hide()
        self.frame = DirectFrame()
        self.frame['image'] = DGG.getDefaultDialogGeom()
        self.frame['image_color'] = CIGlobals.DialogColor
        self.frame['image_scale'] = (-0.9, -0.9, 0.8)
        self.frame['image_pos'] = (0.82, 0, -0.125)
        self.playOrCreateButton = DirectButton(text = "", pos = (0.8125, 0, -0.35), command = self.__action,
                                            geom = CIGlobals.getDefaultBtnGeom(), text_scale = 0.06,
                                            relief = None, text_pos = (0, -0.01))
        self.playOrCreateButton.hide()
        self.deleteButton = DirectButton(text = "Delete", pos = (0.8125, 0, -0.45),
                                        command = self.__action, extraArgs = ['delete'],
                                        geom = CIGlobals.getDefaultBtnGeom(), text_scale = 0.06,
                                        relief = None, text_pos = (0, -0.01))
        self.deleteButton.hide()
        self.quitButton = DirectButton(text = "Quit", pos = (-1.10, 0, -0.925), command = self.__action,
                                    extraArgs = ['quit'], text_scale = 0.06, geom = CIGlobals.getDefaultBtnGeom(),
                                    relief = None, text_pos = (0, -0.01))

        textRolloverColor = Vec4(1, 1, 0, 1)
        textDownColor = Vec4(0.5, 0.9, 1, 1)
        textDisabledColor = Vec4(0.4, 0.8, 0.4, 1)

        for slot in range(6):
            if self.avChooser.hasToonInSlot(slot):
                choice = self.avChooser.getAvChoiceBySlot(slot)
                text = choice.name
            else:
                text = self.NO_TOON
            btn = DirectButton(
                relief=None, text = text, text_scale=0.06,
                text_align=TextNode.ALeft, text1_bg=textDownColor, text2_bg=textRolloverColor,
                text3_fg=textDisabledColor, textMayChange=0, command=self.__handleCharButton,
                extraArgs=[slot], text_pos = (0, 0, 0.0)
            )
            btn.setPythonTag('slot', slot)
            self.charButtons.append(btn)
            btn['state'] = DGG.NORMAL

        gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam')
        listXorigin = -0.02
        listFrameSizeX = 0.625
        listZorigin = -0.43
        listFrameSizeZ = 0.51
        arrowButtonScale = 0.0
        itemFrameXorigin = -0.237
        itemFrameZorigin = 0.365
        buttonXstart = itemFrameXorigin + 0.293

        self.charList = DirectScrolledList(
            relief=None,
            pos=(0.75, 0, -0.225),
            incButton_image=None,
            #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=None,
            #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.charButtons,
            parent = self.frame
        )

        base.camera.setPos(75.12, 63.22, -23)
        base.camera.setHpr(26.57, 9.62, 0)