Example #1
0
    def setup(self):
        # Setting the background to 'water'
        # .self refers back to class(linking it) ensuring it's not just global
        self.showbaseMain.setBackgroundColor((0, 0, 0, 1))
        self.bg = self.showbaseMain.loadObject("water.jpg",
                                               scale=146,
                                               depth=200,
                                               transparency=False)

        # creating & positioning the green buoy
        self.gbuoy = self.showbaseMain.loadObject("Green_buoy.png",
                                                  scale=4,
                                                  depth=50)
        self.gbuoy.setPos(-7, 50, 7)

        # Second green buoy
        self.sgbuoy = self.showbaseMain.loadObject("Green_buoy.png",
                                                   scale=4,
                                                   depth=50)
        self.sgbuoy.setPos(9, 50, 3)

        # creating & positioning the red buoy
        self.rbuoy = self.showbaseMain.loadObject("Red_buoy.png",
                                                  scale=4,
                                                  depth=50)
        self.rbuoy.setPos(2.5, 50, -6)

        # Importing land
        self.sland = self.showbaseMain.loadObject("land.png",
                                                  scale=16,
                                                  depth=50)
        self.sland.setPos(3, 50, 9)
        self.sland.setR(180)

        self.land = self.showbaseMain.loadObject("land.png",
                                                 scale=16,
                                                 depth=50)
        self.land.setPos(-5, 50, -9)

        self.Finflag = self.showbaseMain.loadObject("Finflag.png",
                                                    scale=4,
                                                    depth=50)
        self.Finflag.setPos(15, 50, -10)

        # the 'rope' is the white line that is the
        # sailing course the user must follow
        r = Rope()
        r.setup(4, [(None, (-18, 0, 0)), (None, (-8, 0, -20)),
                    (None, (-15, 0, 15)), (None, (0, 0, 10)),
                    (None, (0, 0, -25)), (None, (10, 0, 10)),
                    (None, (10, 0, 10)), (None, (15, 0, -10))])
        r.ropeNode.setThickness(10)
        r.setPos(0, 55, 0)
        r.reparentTo(camera)

        self.curve = r.ropeNode.getCurve()
        self.curvePoints = r.getPoints(50)
        print(self.curvePoints)
Example #2
0
 def _smooth_path(self, path, smooth_factor=0.5):
     if len(path)<4 or smooth_factor <0.01:
         return path
     r=Rope()
     verts=[(None, point) for point in path]
     r.setup(order=4, verts=verts, knots = None)
     #r.ropeNode.setThickness(2.0)
     #r.reparentTo(render)
     #r.setColor(1,0,1, 1)
     #r.setZ(0.5)
     return r.getPoints(int(len(path)*smooth_factor))
Example #3
0
class HangUpAttack(Attack):
    notify = directNotify.newCategory('HangUpAttack')
    attack = 'hangup'

    def __init__(self, attacksClass, suit):
        Attack.__init__(self, attacksClass, suit)
        self.phone = None
        self.receiver = None
        self.collNP = None
        self.phoneSfx = None
        self.hangupSfx = None
        self.shootIval = None
        self.cord = None
        self.receiverOutCord = None
        self.phoneOutCord = None
        return

    def loadAttack(self):
        self.phone = loader.loadModel('phase_3.5/models/props/phone.bam')
        self.phone.setHpr(0, 0, 180)
        if self.suit.type == 'B':
            self.phone.setPos(0.7, 0.15, 0)
        elif self.suit.type == 'C':
            self.phone.setPos(0.25, 0, 0)
        self.receiver = loader.loadModel('phase_3.5/models/props/receiver.bam')
        self.receiver.reparentTo(self.phone)
        self.cord = Rope()
        self.cord.ropeNode.setUseVertexColor(1)
        self.cord.ropeNode.setUseVertexThickness(1)
        self.cord.setup(3, ({'node': self.phone,
          'point': (0.8, 0, 0.2),
          'color': (0, 0, 0, 1),
          'thickness': 1000}, {'node': self.phone,
          'point': (2, 0, 0),
          'color': (0, 0, 0, 1),
          'thickness': 1000}, {'node': self.receiver,
          'point': (1.1, 0.25, 0.5),
          'color': (0, 0, 0, 1),
          'thickness': 1000}), [])
        self.cord.setH(180)
        self.phoneSfx = base.audio3d.loadSfx('phase_3.5/audio/sfx/SA_hangup.mp3')
        base.audio3d.attachSoundToObject(self.phoneSfx, self.phone)
        self.hangupSfx = base.audio3d.loadSfx('phase_3.5/audio/sfx/SA_hangup_place_down.mp3')
        base.audio3d.attachSoundToObject(self.hangupSfx, self.phone)
        collSphere = CollisionSphere(0, 0, 0, 2)
        collSphere.setTangible(0)
        collNode = CollisionNode('phone_shootout')
        collNode.addSolid(collSphere)
        collNode.setCollideMask(CIGlobals.WallBitmask)
        self.collNP = self.phone.attachNewNode(collNode)

    def doAttack(self, ts = 0):
        self.loadAttack()
        if hasattr(self.suit, 'uniqueName'):
            name = self.suit.uniqueName('doHangupAttack')
        else:
            name = 'doHangupAttack'
        if self.suit.type == 'A':
            delay2playSound = 1.0
            delayAfterSoundToPlaceDownReceiver = 0.2
            delayAfterShootToIgnoreCollisions = 1.0
            delay2PickUpReceiver = 1.0
            receiverInHandPos = Point3(-0.5, 0.5, -1)
        elif self.suit.type == 'B':
            delay2playSound = 1.5
            delayAfterSoundToPlaceDownReceiver = 0.7
            delayAfterShootToIgnoreCollisions = 1.0
            delay2PickUpReceiver = 1.5
            receiverInHandPos = Point3(-0.3, 0.5, -0.8)
        elif self.suit.type == 'C':
            delay2playSound = 1.0
            delayAfterSoundToPlaceDownReceiver = 1.15
            delayAfterShootToIgnoreCollisions = 1.0
            delay2PickUpReceiver = 1.5
            receiverInHandPos = Point3(-0.3, 0.5, -0.8)
        self.suitTrack = Parallel(name=name)
        self.suitTrack.append(ActorInterval(self.suit, 'phone'))
        self.suitTrack.append(Sequence(Wait(delay2playSound), SoundInterval(self.phoneSfx, duration=2.1), Wait(delayAfterSoundToPlaceDownReceiver), Func(self.receiver.setPos, 0, 0, 0), Func(self.receiver.setH, 0.0), Func(self.receiver.reparentTo, self.phone), Func(self.acceptOnce, 'enter' + self.collNP.node().getName(), self.handleCollision), Func(self.shootOut), Parallel(SoundInterval(self.hangupSfx), Sequence(Wait(delayAfterShootToIgnoreCollisions), Func(self.ignore, 'enter' + self.collNP.node().getName())))))
        self.suitTrack.append(Sequence(Func(self.phone.reparentTo, self.suit.find('**/joint_Lhold')), Func(self.cord.reparentTo, render), Wait(delay2PickUpReceiver), Func(self.receiver.reparentTo, self.suit.find('**/joint_Rhold')), Func(self.receiver.setPos, receiverInHandPos), Func(self.receiver.setH, 270.0)))
        self.suitTrack.setDoneEvent(self.suitTrack.getName())
        self.acceptOnce(self.suitTrack.getDoneEvent(), self.finishedAttack)
        self.suitTrack.delayDelete = DelayDelete.DelayDelete(self.suit, name)
        self.suitTrack.start(ts)

    def handleCollision(self, entry):
        if self.suit:
            self.suit.sendUpdate('toonHitByWeapon', [self.getAttackId(self.attack), base.localAvatar.doId])
            base.localAvatar.b_handleSuitAttack(self.getAttackId(self.attack), self.suit.doId)

    def shootOut(self):
        pathNode = NodePath('path')
        pathNode.reparentTo(self.suit)
        pathNode.setPos(0, 50, self.phone.getZ(self.suit))
        self.collNP.reparentTo(render)
        self.shootIval = LerpPosInterval(self.collNP, duration=1.0, pos=pathNode.getPos(render), startPos=self.phone.getPos(render))
        self.shootIval.start()
        pathNode.removeNode()
        del pathNode

    def cleanup(self):
        Attack.cleanup(self)
        if self.shootIval:
            self.shootIval.pause()
            self.shootIval = None
        if self.cord:
            self.cord.removeNode()
            self.cord = None
        if self.phone:
            self.phone.removeNode()
            self.phone = None
        if self.receiver:
            self.receiver.removeNode()
            self.receiver = None
        if self.collNP:
            self.collNP.node().clearSolids()
            self.collNP.removeNode()
            self.collNP = None
        if self.phoneSfx:
            self.phoneSfx.stop()
            self.phoneSfx = None
        return
Example #4
0
class CurveEditor(DirectObject):
    """ CurveEditor will create and edit the curve """
    def __init__(self, editor):
        self.editor = editor
        self.i = 0
        self.ropeNum = 0
        self.curve = []
        self.curveControl = []
        self.currentRope = None
        self.degree = 3

    def createCurve(self):
        if self.editor.mode == self.editor.CREATE_CURVE_MODE:
            self.view = self.editor.ui.currentView

            #Get the mouse position
            x = base.direct.dr.mouseX
            y = base.direct.dr.mouseY

            if self.editor.fMoveCamera == False and self.view != None:
                self.createControler(x,y)
                if self.currentRope != None:
                    self.currentRope.detachNode()
                self.ropeUpdate(self.curve)
                self.accept("DIRECT-enter", self.onBaseMode)

            self.accept("DIRECT-enter", self.onBaseMode)

    def editCurve(self, task):
        if self.editor.mode == self.editor.EDIT_CURVE_MODE:
            if self.editor.fMoveCamera == False:
                self.selected = None
                self.selected = base.direct.selected.last
                if self.selected != None:
                    for item in self.curveControl:
                        if item[1] == self.selected:
                            self.point = item  #temporarily save the controler information for further use
                            self.currentCurve = self.currentRope.ropeNode.getCurve()
                            self.currentCurve.setVertex(item[0], self.selected.getPos())
                            self.accept("DIRECT-delete", self.onControlerDelete)
                            return task.cont

    def onControlerDelete(self):
        if self.editor.mode == self.editor.EDIT_CURVE_MODE:
            self.curve.remove(self.curve[self.point[0]])
            #reset the controller list
            for item in self.curveControl:
                if item[0] > self.point[0]:
                    newname = 'controler%d' % (item[0]-1)
                    item[1].setName(newname)
                    self.curveControl[item[0]] = (item[0]-1, item[1])
            self.curveControl.remove(self.point)
            self.currentRope.setup(self.degree,self.curve)

    def ropeUpdate(self, curve):
        self.currentRope = Rope()
        self.currentRope.setup(self.degree, curve)
        self.currentRope.reparentTo(render)

    def onBaseMode(self):
        self.editor.preMode = self.editor.mode
        self.editor.mode = self.editor.BASE_MODE
        self.editor.ui.editCurveMenuItem.Check(False)
        self.editor.ui.createCurveMenuItem.Check(False)
        self.i = 0
        for item in self.curveControl:
            item[1].hide()
        if self.editor.preMode == self.editor.BASE_MODE :
            pass
        if self.editor.preMode == self.editor.CREATE_CURVE_MODE :
            self.updateScene()
        if self.editor.preMode == self.editor.EDIT_CURVE_MODE :
            self.doneEdit()
        self.curveControl = []
        self.curve = []
        self.currentRope = None
        base.direct.manipulationControl.enableManipulation()
        self.editor.ui.createCurveMenuItem.Check(False)
        self.editor.ui.editCurveMenuItem.Check(False)

    def updateScene(self):
        curveObjNP = self.editor.objectMgr.addNewCurve(self.curveControl, self.degree, nodePath=self.currentRope)
        curveObj = self.editor.objectMgr.findObjectByNodePath(curveObjNP)
        for item in self.curveControl:
            item[1].reparentTo(curveObjNP)
        self.editor.objectMgr.updateObjectPropValue(curveObj, 'Degree', self.degree, fSelectObject=False, fUndo=False)

    def doneEdit(self):
        base.direct.selected.last = None

    def createControler(self, x, y):
        if self.view != None:
            self.controler = render.attachNewNode("controler")
            self.controler = loader.loadModel('models/misc/smiley')
            controlerPathname = 'controler%d' % self.i
            self.controler.setName(controlerPathname)
            self.controler.setColor(0, 0, 0, 1)
            self.controler.setScale(0.2)
            self.controler.reparentTo(render)
            self.controler.setTag('OBJRoot','1')
            self.controler.setTag('Controller','1') #controller Tag
            self.i += 1

            iRay = SelectionRay(self.view.camera)
            iRay.collider.setFromLens(self.view.camNode, x, y)
            iRay.collideWithBitMask(BitMask32.bit(21))
            iRay.ct.traverse(self.view.collPlane)
            if iRay.getNumEntries() > 0:
                entry = iRay.getEntry(0)
                hitPt = entry.getSurfacePoint(entry.getFromNodePath())

            if hitPt:
                # create a temp nodePath to get the position
                np = NodePath('temp')
                np.setPos(self.view.camera, hitPt)

                if base.direct.manipulationControl.fGridSnap:
                    snappedPos = self.view.grid.computeSnapPoint(np.getPos())
                    np.setPos(snappedPos)

                # update temp nodePath's HPR and scale with newobj's
                np.setHpr(self.controler.getHpr())
                np.setScale(self.controler.getScale())

                # transform newobj to cursor position
                self.controler.setMat(Mat4(np.getMat()))
                np.remove()
            iRay.collisionNodePath.removeNode()
            del iRay

            self.curve.append((None, self.controler.getPos()))
            self.curveControl.append((self.i-1, self.controler))
Example #5
0
class CurveEditor(DirectObject):
    """ CurveEditor will create and edit the curve """
    def __init__(self, editor):
        self.editor = editor
        self.i = 0
        self.ropeNum = 0
        self.curve = []
        self.curveControl = []
        self.currentRope = None
        self.degree = 3

    def createCurve(self):
        if self.editor.mode == self.editor.CREATE_CURVE_MODE:
            self.view = self.editor.ui.currentView

            #Get the mouse position
            x = base.direct.dr.mouseX
            y = base.direct.dr.mouseY

            if self.editor.fMoveCamera == False and self.view != None:
                self.createControler(x,y)
                if self.currentRope != None:
                    self.currentRope.detachNode()
                self.ropeUpdate(self.curve)
                self.accept("DIRECT-enter", self.onBaseMode)

            self.accept("DIRECT-enter", self.onBaseMode)

    def editCurve(self, task):
        if self.editor.mode == self.editor.EDIT_CURVE_MODE:
            if self.editor.fMoveCamera == False:
                self.selected = None
                self.selected = base.direct.selected.last
                if self.selected != None:
                    for item in self.curveControl:
                        if item[1] == self.selected:
                            self.point = item  #temporarily save the controler information for further use
                            self.currentCurve = self.currentRope.ropeNode.getCurve()
                            self.currentCurve.setVertex(item[0], self.selected.getPos())
                            self.accept("DIRECT-delete", self.onControlerDelete)
                            return task.cont

    def onControlerDelete(self):
        if self.editor.mode == self.editor.EDIT_CURVE_MODE:
            self.curve.remove(self.curve[self.point[0]])
            #reset the controller list
            for item in self.curveControl:
                if item[0] > self.point[0]:
                    newname = 'controler%d' % (item[0]-1)
                    item[1].setName(newname)
                    self.curveControl[item[0]] = (item[0]-1, item[1])
            self.curveControl.remove(self.point)
            self.currentRope.setup(self.degree,self.curve)

    def ropeUpdate(self, curve):
        self.currentRope = Rope()
        self.currentRope.setup(self.degree, curve)
        self.currentRope.reparentTo(render)

    def onBaseMode(self):
        self.editor.preMode = self.editor.mode
        self.editor.mode = self.editor.BASE_MODE
        self.editor.ui.editCurveMenuItem.Check(False)
        self.editor.ui.createCurveMenuItem.Check(False)
        self.i = 0
        for item in self.curveControl:
            item[1].hide()
        if self.editor.preMode == self.editor.BASE_MODE :
            pass
        if self.editor.preMode == self.editor.CREATE_CURVE_MODE :
            self.updateScene()
        if self.editor.preMode == self.editor.EDIT_CURVE_MODE :
            self.doneEdit()
        self.curveControl = []
        self.curve = []
        self.currentRope = None
        base.direct.manipulationControl.enableManipulation()
        self.editor.ui.createCurveMenuItem.Check(False)
        self.editor.ui.editCurveMenuItem.Check(False)

    def updateScene(self):
        curveObjNP = self.editor.objectMgr.addNewCurve(self.curveControl, self.degree, nodePath=self.currentRope)
        curveObj = self.editor.objectMgr.findObjectByNodePath(curveObjNP)
        for item in self.curveControl:
            item[1].reparentTo(curveObjNP)
        self.editor.objectMgr.updateObjectPropValue(curveObj, 'Degree', self.degree, fSelectObject=False, fUndo=False)

    def doneEdit(self):
        base.direct.selected.last = None

    def createControler(self, x, y):
        if self.view != None:
            self.controler = render.attachNewNode("controler")
            self.controler = loader.loadModel('models/misc/smiley')
            controlerPathname = 'controler%d' % self.i
            self.controler.setName(controlerPathname)
            self.controler.setColor(0, 0, 0, 1)
            self.controler.setScale(0.2)
            self.controler.reparentTo(render)
            self.controler.setTag('OBJRoot','1')
            self.controler.setTag('Controller','1') #controller Tag
            self.i += 1

            iRay = SelectionRay(self.view.camera)
            iRay.collider.setFromLens(self.view.camNode, x, y)
            iRay.collideWithBitMask(BitMask32.bit(21))
            iRay.ct.traverse(self.view.collPlane)
            if iRay.getNumEntries() > 0:
                entry = iRay.getEntry(0)
                hitPt = entry.getSurfacePoint(entry.getFromNodePath())

            if hitPt:
                # create a temp nodePath to get the position
                np = NodePath('temp')
                np.setPos(self.view.camera, hitPt)

                if base.direct.manipulationControl.fGridSnap:
                    snappedPos = self.view.grid.computeSnapPoint(np.getPos())
                    np.setPos(snappedPos)

                # update temp nodePath's HPR and scale with newobj's
                np.setHpr(self.controler.getHpr())
                np.setScale(self.controler.getScale())

                # transform newobj to cursor position
                self.controler.setMat(Mat4(np.getMat()))
                np.remove()
            iRay.collisionNodePath.removeNode()
            del iRay

            self.curve.append((None, self.controler.getPos()))
            self.curveControl.append((self.i-1, self.controler))
Example #6
0
class DistributedDeliveryTruck(DistributedNode):
    notify = directNotify.newCategory('DistributedDeliveryTruck')
    barrelscale = 0.15
    barrelpoints = [(1.05, 2.68, 0.84), (0, 2.68, 0.84), (-1.05, 2.68, 0.84),
                    (1.05, 3.68, 0.84), (0, 3.68, 0.84), (-1.05, 3.68, 0.84),
                    (1.05, 4.68, 0.84), (0, 4.68, 0.84), (-1.05, 4.68, 0.84),
                    (1.05, 5.68, 0.84), (0, 5.68, 0.84), (-1.05, 5.68, 0.84),
                    (1.05, 6.68, 0.84), (0, 6.68, 0.84), (-1.05, 6.68, 0.84),
                    (1.05, 7.68, 0.84), (0, 7.68, 0.84), (-1.05, 7.68, 0.84)]

    def __init__(self, cr):
        DistributedNode.__init__(self, cr)
        self.kart = None
        self.rope = None
        self.pod = None
        self.barrels = []
        self.numBarrels = 0
        self.triggerNP = None
        self.mg = None
        return

    def setNumBarrels(self, num):
        self.numBarrels = num
        self.__generateBarrels()

    def getNumBarrels(self):
        return self.numBarrels

    def __removeAllBarrels(self):
        for barrel in self.barrels:
            barrel.removeNode()

        self.barrels = []

    def __generateBarrels(self):
        self.__removeAllBarrels()
        for i in xrange(self.numBarrels):
            point = self.barrelpoints[i]
            barrel = loader.loadModel('phase_4/models/cogHQ/gagTank.bam')
            barrel.setScale(self.barrelscale)
            barrel.setPos(point)
            barrel.setH(180)
            barrel.reparentTo(self)
            self.barrels.append(barrel)

    def __handleTruckTrigger(self, entry):
        if not base.localAvatar.hasBarrel:
            self.sendUpdate('requestBarrel')

    def announceGenerate(self):
        DistributedNode.announceGenerate(self)
        self.kart = loader.loadModel('phase_6/models/karting/Kart3_Final.bam')
        self.kart.find('**/decals').removeNode()
        self.kart.reparentTo(self)
        self.pod = loader.loadModel('phase_4/models/minigames/pods_truck.egg')
        self.pod.reparentTo(self)
        self.pod.setScale(0.2)
        self.pod.setY(8.5)
        self.pod.setH(180)
        self.pod.find('**/metal_ramp').setBin('ground', 18)
        self.pod.find('**/metal_ramp_coll').setCollideMask(
            CIGlobals.FloorBitmask)
        self.rope = Rope()
        self.rope.ropeNode.setUseVertexColor(1)
        self.rope.setup(3, ({
            'node': self.kart,
            'point': (0, 1.5, 0.7),
            'color': (0, 0, 0, 1),
            'thickness': 1000
        }, {
            'node': self.kart,
            'point': (0, 1.5, 0.7),
            'color': (0, 0, 0, 1),
            'thickness': 1000
        }, {
            'node': self.pod,
            'point': (0, 31, 5),
            'color': (0, 0, 0, 1),
            'thickness': 1000
        }), [])
        self.rope.setH(180)
        self.rope.reparentTo(self)
        sphere = CollisionSphere(0, 0, 0, 2)
        sphere.setTangible(0)
        node = CollisionNode(self.uniqueName('truck_trigger'))
        node.addSolid(sphere)
        node.setCollideMask(CIGlobals.WallBitmask)
        self.triggerNP = self.attachNewNode(node)
        self.triggerNP.setPos(0, 8.0, 2.0)
        self.setScale(2.0)
        self.accept('enter' + self.triggerNP.node().getName(),
                    self.__handleTruckTrigger)

    def disable(self):
        self.ignore('enter' + self.triggerNP.node().getName())
        self.__removeAllBarrels()
        self.barrels = None
        self.numBarrels = None
        if self.rope:
            self.rope.removeNode()
            self.rope = None
        if self.pod:
            self.pod.removeNode()
            self.pod = None
        if self.kart:
            self.kart.removeNode()
            self.kart = None
        self.mg = None
        DistributedNode.disable(self)
        return
class HangUpAttack(Attack):
    notify = directNotify.newCategory('HangUpAttack')
    attack = 'hangup'

    def __init__(self, attacksClass, suit):
        Attack.__init__(self, attacksClass, suit)
        self.phone = None
        self.receiver = None
        self.collNP = None
        self.phoneSfx = None
        self.hangupSfx = None
        self.shootIval = None
        self.cord = None
        self.receiverOutCord = None
        self.phoneOutCord = None
        return

    def loadAttack(self):
        self.phone = loader.loadModel('phase_3.5/models/props/phone.bam')
        self.phone.setHpr(0, 0, 180)
        if self.suit.type == 'B':
            self.phone.setPos(0.7, 0.15, 0)
        else:
            if self.suit.type == 'C':
                self.phone.setPos(0.25, 0, 0)
        self.receiver = loader.loadModel('phase_3.5/models/props/receiver.bam')
        self.receiver.reparentTo(self.phone)
        self.cord = Rope()
        self.cord.ropeNode.setUseVertexColor(1)
        self.cord.ropeNode.setUseVertexThickness(1)
        self.cord.setup(3, ({'node': self.phone, 'point': (0.8, 0, 0.2), 'color': (0, 0, 0, 1), 'thickness': 1000}, {'node': self.phone, 'point': (2, 0, 0), 'color': (0, 0, 0, 1), 'thickness': 1000}, {'node': self.receiver, 'point': (1.1, 0.25, 0.5), 'color': (0, 0, 0, 1), 'thickness': 1000}), [])
        self.cord.setH(180)
        self.phoneSfx = base.audio3d.loadSfx('phase_3.5/audio/sfx/SA_hangup.ogg')
        base.audio3d.attachSoundToObject(self.phoneSfx, self.phone)
        self.hangupSfx = base.audio3d.loadSfx('phase_3.5/audio/sfx/SA_hangup_place_down.ogg')
        base.audio3d.attachSoundToObject(self.hangupSfx, self.phone)
        collSphere = CollisionSphere(0, 0, 0, 2)
        collSphere.setTangible(0)
        collNode = CollisionNode('phone_shootout')
        collNode.addSolid(collSphere)
        collNode.setCollideMask(CIGlobals.WallBitmask)
        self.collNP = self.phone.attachNewNode(collNode)

    def doAttack(self, ts=0):
        self.loadAttack()
        if hasattr(self.suit, 'uniqueName'):
            name = self.suit.uniqueName('doHangupAttack')
        else:
            name = 'doHangupAttack'
        if self.suit.type == 'A':
            delay2playSound = 1.0
            delayAfterSoundToPlaceDownReceiver = 0.2
            delayAfterShootToIgnoreCollisions = 1.0
            delay2PickUpReceiver = 1.0
            receiverInHandPos = Point3(-0.5, 0.5, -1)
        else:
            if self.suit.type == 'B':
                delay2playSound = 1.5
                delayAfterSoundToPlaceDownReceiver = 0.7
                delayAfterShootToIgnoreCollisions = 1.0
                delay2PickUpReceiver = 1.5
                receiverInHandPos = Point3(-0.3, 0.5, -0.8)
            else:
                if self.suit.type == 'C':
                    delay2playSound = 1.0
                    delayAfterSoundToPlaceDownReceiver = 1.15
                    delayAfterShootToIgnoreCollisions = 1.0
                    delay2PickUpReceiver = 1.5
                    receiverInHandPos = Point3(-0.3, 0.5, -0.8)
        self.suitTrack = Parallel(name=name)
        self.suitTrack.append(ActorInterval(self.suit, 'phone'))
        self.suitTrack.append(Sequence(Wait(delay2playSound), SoundInterval(self.phoneSfx, duration=2.1), Wait(delayAfterSoundToPlaceDownReceiver), Func(self.receiver.setPos, 0, 0, 0), Func(self.receiver.setH, 0.0), Func(self.receiver.reparentTo, self.phone), Func(self.acceptOnce, 'enter' + self.collNP.node().getName(), self.handleCollision), Func(self.shootOut), Parallel(SoundInterval(self.hangupSfx), Sequence(Wait(delayAfterShootToIgnoreCollisions), Func(self.ignore, 'enter' + self.collNP.node().getName())))))
        self.suitTrack.append(Sequence(Func(self.phone.reparentTo, self.suit.find('**/joint_Lhold')), Func(self.cord.reparentTo, render), Wait(delay2PickUpReceiver), Func(self.receiver.reparentTo, self.suit.find('**/joint_Rhold')), Func(self.receiver.setPos, receiverInHandPos), Func(self.receiver.setH, 270.0)))
        self.suitTrack.setDoneEvent(self.suitTrack.getName())
        self.acceptOnce(self.suitTrack.getDoneEvent(), self.finishedAttack)
        self.suitTrack.delayDelete = DelayDelete.DelayDelete(self.suit, name)
        self.suitTrack.start(ts)

    def handleCollision(self, entry):
        if self.suit:
            self.suit.sendUpdate('toonHitByWeapon', [self.getAttackId(self.attack), base.localAvatar.doId])
            base.localAvatar.b_handleSuitAttack(self.getAttackId(self.attack), self.suit.doId)

    def shootOut(self):
        pathNode = NodePath('path')
        pathNode.reparentTo(self.suit)
        pathNode.setPos(0, 50, self.phone.getZ(self.suit))
        self.collNP.reparentTo(render)
        self.shootIval = LerpPosInterval(self.collNP, duration=1.0, pos=pathNode.getPos(render), startPos=self.phone.getPos(render))
        self.shootIval.start()
        pathNode.removeNode()
        del pathNode

    def cleanup(self):
        Attack.cleanup(self)
        if self.shootIval:
            self.shootIval.pause()
            self.shootIval = None
        if self.cord:
            self.cord.removeNode()
            self.cord = None
        if self.phone:
            self.phone.removeNode()
            self.phone = None
        if self.receiver:
            self.receiver.removeNode()
            self.receiver = None
        if self.collNP:
            self.collNP.node().clearSolids()
            self.collNP.removeNode()
            self.collNP = None
        if self.phoneSfx:
            self.phoneSfx.stop()
            self.phoneSfx = None
        return
class DistributedDeliveryTruck(DistributedNode):
    notify = directNotify.newCategory('DistributedDeliveryTruck')
    barrelscale = 0.15
    barrelpoints = [(1.05, 2.68, 0.84),
     (0, 2.68, 0.84),
     (-1.05, 2.68, 0.84),
     (1.05, 3.68, 0.84),
     (0, 3.68, 0.84),
     (-1.05, 3.68, 0.84),
     (1.05, 4.68, 0.84),
     (0, 4.68, 0.84),
     (-1.05, 4.68, 0.84),
     (1.05, 5.68, 0.84),
     (0, 5.68, 0.84),
     (-1.05, 5.68, 0.84),
     (1.05, 6.68, 0.84),
     (0, 6.68, 0.84),
     (-1.05, 6.68, 0.84),
     (1.05, 7.68, 0.84),
     (0, 7.68, 0.84),
     (-1.05, 7.68, 0.84)]

    def __init__(self, cr):
        DistributedNode.__init__(self, cr)
        self.kart = None
        self.rope = None
        self.pod = None
        self.barrels = []
        self.numBarrels = 0
        self.triggerNP = None
        self.mg = None
        return

    def setNumBarrels(self, num):
        self.numBarrels = num
        self.__generateBarrels()

    def getNumBarrels(self):
        return self.numBarrels

    def __removeAllBarrels(self):
        for barrel in self.barrels:
            barrel.removeNode()

        self.barrels = []

    def __generateBarrels(self):
        self.__removeAllBarrels()
        for i in xrange(self.numBarrels):
            point = self.barrelpoints[i]
            barrel = loader.loadModel('phase_4/models/cogHQ/gagTank.bam')
            barrel.setScale(self.barrelscale)
            barrel.setPos(point)
            barrel.setH(180)
            barrel.reparentTo(self)
            self.barrels.append(barrel)

    def __handleTruckTrigger(self, entry):
        if not base.localAvatar.hasBarrel:
            self.sendUpdate('requestBarrel')

    def announceGenerate(self):
        DistributedNode.announceGenerate(self)
        self.kart = loader.loadModel('phase_6/models/karting/Kart3_Final.bam')
        self.kart.find('**/decals').removeNode()
        self.kart.reparentTo(self)
        self.pod = loader.loadModel('phase_4/models/minigames/pods_truck.egg')
        self.pod.reparentTo(self)
        self.pod.setScale(0.2)
        self.pod.setY(8.5)
        self.pod.setH(180)
        self.rope = Rope()
        self.rope.ropeNode.setUseVertexColor(1)
        self.rope.setup(3, ({'node': self.kart,
          'point': (0, 1.5, 0.7),
          'color': (0, 0, 0, 1),
          'thickness': 1000}, {'node': self.kart,
          'point': (0, 1.5, 0.7),
          'color': (0, 0, 0, 1),
          'thickness': 1000}, {'node': self.pod,
          'point': (0, 31, 5),
          'color': (0, 0, 0, 1),
          'thickness': 1000}), [])
        self.rope.setH(180)
        self.rope.reparentTo(self)
        sphere = CollisionSphere(0, 0, 0, 2)
        sphere.setTangible(0)
        node = CollisionNode(self.uniqueName('truck_trigger'))
        node.addSolid(sphere)
        node.setCollideMask(CIGlobals.WallBitmask)
        self.triggerNP = self.attachNewNode(node)
        self.triggerNP.setPos(0, 8.0, 2.0)
        self.setScale(2.0)
        self.accept('enter' + self.triggerNP.node().getName(), self.__handleTruckTrigger)

    def disable(self):
        self.ignore('enter' + self.triggerNP.node().getName())
        self.__removeAllBarrels()
        self.barrels = None
        self.numBarrels = None
        if self.rope:
            self.rope.removeNode()
            self.rope = None
        if self.pod:
            self.pod.removeNode()
            self.pod = None
        if self.kart:
            self.kart.removeNode()
            self.kart = None
        self.mg = None
        DistributedNode.disable(self)
        return