class PlacementGhost(GameObject):
    def __init__(self,player,type,scale):
        self.type = type
        self.player = player
        self.node_path = NodePath("PlacementGhost")
        self.scale = scale
        self.model_dict = {"army":["../models/infantry_counter_grey.egg","../models/infantry_counter_red.egg","../models/infantry_counter_green.egg"],"tower":["../models/tower_grey.egg","../models/tower_red.egg","../models/tower_green.egg"]}
        self.model = loader.loadModel(self.model_dict[type][player])
        self.model.reparentTo(self.node_path)
        self.node_path.reparentTo(render)
        self.node_path.setScale(self.scale,self.scale,self.scale)
        self.node_path.setColor(1,1,1,0.4)
        self.node_path.setTransparency(True)

    def place(self,type,x,y):
        if self.type == "tower":
            tower = Tower(self.player,base.object_scale,self.node_path.getX(),self.node_path.getY())
            return tower
        if self.type == "army":
            army = Army(self.player,base.object_scale,self.node_path.getX(),self.node_path.getY())
            return army

    def change_player(self,player):
        if base.state == "placement":
            self.model.remove()
            self.player = player
            self.model = loader.loadModel(self.model_dict[self.type][self.player])
            self.model.reparentTo(self.node_path)

    def change_type(self,type):
        if base.state == "placement":
            self.model.remove()
            self.type = type
            self.model = loader.loadModel(self.model_dict[self.type][self.player])
            self.model.reparentTo(self.node_path)
class PlacementGhost(GameObject):
    def __init__(self, player, type, scale):
        self.type = type
        self.player = player
        self.node_path = NodePath("PlacementGhost")
        self.scale = scale
        self.model_dict = {
            "army": [
                "../models/infantry_counter_grey.egg",
                "../models/infantry_counter_red.egg",
                "../models/infantry_counter_green.egg"
            ],
            "tower": [
                "../models/tower_grey.egg", "../models/tower_red.egg",
                "../models/tower_green.egg"
            ]
        }
        self.model = loader.loadModel(self.model_dict[type][player])
        self.model.reparentTo(self.node_path)
        self.node_path.reparentTo(render)
        self.node_path.setScale(self.scale, self.scale, self.scale)
        self.node_path.setColor(1, 1, 1, 0.4)
        self.node_path.setTransparency(True)

    def place(self, type, x, y):
        if self.type == "tower":
            tower = Tower(self.player, base.object_scale,
                          self.node_path.getX(), self.node_path.getY())
            return tower
        if self.type == "army":
            army = Army(self.player, base.object_scale, self.node_path.getX(),
                        self.node_path.getY())
            return army

    def change_player(self, player):
        if base.state == "placement":
            self.model.remove()
            self.player = player
            self.model = loader.loadModel(
                self.model_dict[self.type][self.player])
            self.model.reparentTo(self.node_path)

    def change_type(self, type):
        if base.state == "placement":
            self.model.remove()
            self.type = type
            self.model = loader.loadModel(
                self.model_dict[self.type][self.player])
            self.model.reparentTo(self.node_path)
 def generateToonMoveTrack(self, toon):
     node = NodePath('tempNode')
     displacement = Vec3(toon.getPos(render) - self.getPos(render))
     displacement.setZ(0)
     displacement.normalize()
     movieDistance = self.movieNode.getDistance(self.rotateNode)
     displacement *= movieDistance
     node.reparentTo(render)
     node.setPos(displacement + self.getPos(render))
     node.lookAt(self)
     heading = PythonUtil.fitDestAngle2Src(toon.getH(render),
                                           node.getH(render))
     hpr = toon.getHpr(render)
     hpr.setX(heading)
     finalX = node.getX(render)
     finalY = node.getY(render)
     finalZ = node.getZ(render)
     node.removeNode()
     toonTrack = Sequence(
         Parallel(
             ActorInterval(toon, 'walk', loop=True, duration=1),
             Parallel(
                 LerpPosInterval(toon,
                                 1.0,
                                 Point3(finalX, finalY, toon.getZ(render)),
                                 fluid=True,
                                 bakeInStart=False)),
             LerpHprInterval(toon, 1.0, hpr=hpr)),
         Func(toon.loop, 'neutral'))
     return toonTrack
class Army(GameObject):
    def __init__(self,player,name,x,y,soldiers,general=None):
        global army_count
        self.my_id = army_count
        army_count += 1

        print "ARMY ID IS",self.my_id

        self.name = name
        self.x = x
        self.y = y
        self.target_x = x
        self.target_y = y
        self.scale = counter_scale
        self.range = 50.0

        self.selected = False

        self.general = general
        self.soldiers = soldiers
        self.state = "normal"
        self.speed = 25.0

        self.battle = -1

        self.stat_init = 0.0
        self.stat_hit = 0.0
        self.stat_block = 0.0
        self.stat_delay = 0.0

        self.player = player
        if self.player == 0:
            self.colour = (0.5,0.5,0.5,1)
            self.model = loader.loadModel("models/infantry_counter_grey.egg")
        if self.player == 1:
            self.colour = (1,0,0,1)
            self.model = loader.loadModel("models/infantry_counter_red.egg")
        elif self.player == 2:
            self.colour = (0,1,0,1)
            self.model = loader.loadModel("models/infantry_counter_green.egg")

        self.node_path = NodePath("army"+str(self.my_id)+"_node_path")
        self.model.reparentTo(self.node_path)
        self.node_path.setPos(x,y,0)
        self.node_path.setTag("player",str(player))
        self.node_path.setScale(self.scale,self.scale,self.scale)

        self.node_col = self.node_path.attachNewNode(CollisionNode("army"+str(self.my_id)+"_c_node"))
        self.node_col.setScale((1,1,0.5))
        self.node_col.setPos(0,0,0)
        self.node_col.node().addSolid(CollisionSphere(0,0,0,1))
        self.node_col.setTag("type","army")
        base.cTrav.addCollider(self.node_col,base.col_manager.col_handler)
        #self.node_col.show()
        self.node_path.setTag("id",str(self.my_id))
        self.army_fight_col = self.node_path.attachNewNode(CollisionNode("army"+str(self.my_id)+"_batcol_node"))
        self.army_fight_col.setScale((2,2,0.5))
        self.army_fight_col.setPos(0,0,0)
        self.army_fight_col.node().addSolid(CollisionSphere(0,0,0,1))
        self.army_fight_col.setColor(1,0,0,0.1)
        self.army_fight_col.setTag("player",str(player))
        self.army_fight_col.setTag("state","normal")
        self.army_fight_col.setTag("type","army")
        base.cTrav.addCollider(self.army_fight_col,base.col_manager.col_handler)
        #self.army_fight_col.show()

        self.selection_ring = self.selection_ring_create(size = 1.2)
        self.selection_ring.reparentTo(self.node_path)
        self.selection_ring.hide()

        self.node_path.reparentTo(render)

    def turn_start(self):
        rate = 0.5
        army_scl_up = self.model.scaleInterval(rate, Point3(1.5, 1.5, 1.5))
        army_scl_down = self.model.scaleInterval(rate, Point3(1, 1, 1))
        self.sq_army_bat = Sequence(army_scl_up,army_scl_down)
        self.sq_army_bat.loop()

    def turn_end(self):
        try:
            self.sq_army_bat.finish()
        except:
            print "no sequence to end"

    def die(self):
        if base.single_player == False and base.client == False:
            base.net_manager.server_messager("army_kill",[self.my_id])
        self.state = "dead"
        self.army_fight_col.removeNode()
        self.node_col.removeNode()
        rate = 4
        intvl_shrink = self.model.scaleInterval(rate, Point3(0, 0, 0))
        func_destroy = Func(self.destroy)
        self.sq_die = Sequence(intvl_shrink,func_destroy)
        self.sq_die.start()
        base.battles[self.battle].recenter()
        base.battles[self.battle].shrink()
        if self.selected:
            i = base.col_manager.selecteds.index(self)
            del base.col_manager.selecteds[i]

    def stop(self):
        try:
            self.sq_army_move.pause()
        except:
            print "already stopped"

    def move_to_point(self,tx,ty):
            self.target_x = tx
            self.target_y = ty
            dist = float(TCalc.dist_to_point(self.node_path.getX(),self.node_path.getY(),tx,ty))
            print dist
            #time = dist/speed
            #print dist/speed
            #print time*speed,dist
            try:
                self.sq_army_move.pause()
                self.intvl_army_move = None
            except:
                print "no sequence"

            if dist > 1:
                self.intvl_army_move = self.node_path.posInterval(dist/self.speed, Point3(self.target_x, self.target_y, 0),startPos=Point3(self.node_path.getX(), self.node_path.getY(), 0))
                self.sq_army_move = Sequence(self.intvl_army_move)
                self.sq_army_move.start()
            else:
                try:
                    self.sq_army_move.finish()
                except:
                    print "no sequence"

    def set_target(self,sender,tx,ty):
        if self.state == "normal":
            if base.single_player == False:
                base.net_manager.army_move(self.my_id,tx,ty)
            else:
                self.move_to_point(tx,ty)

    def battle_shuffle(self,tx,ty):
        if base.single_player == False:
            base.net_manager.army_move(self.my_id,tx,ty)
        else:
            self.move_to_point(tx,ty)
Exemple #5
0
class Player(DirectObject):
    def __init__(self, _main):
        self.main = _main

        # Stats
        self.moveSpeed = 8
        self.inventory = []
        self.maxCarryWeight = 20.0 #kg ?
        self.currentInventoryWeight = 0.0

        # Inventory GUI
        self.inventoryGui = Inventory()
        self.inventoryGui.hide()
        self.inventoryActive = False
        self.craftInventory = CraftInventory()
        self.craftInventory.hide()

        # enable movements through the level
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0}
        self.player = NodePath("Player")#loader.loadModel("smiley")
        self.player.setPos(149.032, 329.324, 11.3384)
        self.player.setH(180)
        self.player.reparentTo(render)

        self.accept("w", self.setKey, ["forward",1])
        self.accept("w-up", self.setKey, ["forward",0])
        self.accept("a", self.setKey, ["left",1])
        self.accept("a-up", self.setKey, ["left",0])
        self.accept("s", self.setKey, ["backward",1])
        self.accept("s-up", self.setKey, ["backward",0])
        self.accept("d", self.setKey, ["right",1])
        self.accept("d-up", self.setKey, ["right",0])
        self.accept("mouse1", self.handleLeftMouse)
        self.accept("i", self.toggleInventory)
        self.accept("c", self.toggleCraftInventory)


        # screen sizes
        self.winXhalf = base.win.getXSize() / 2
        self.winYhalf = base.win.getYSize() / 2

        self.mouseSpeedX = 0.1
        self.mouseSpeedY = 0.1

        camera.setH(180)
        camera.reparentTo(self.player)
        camera.setZ(self.player, 2)
        base.camLens.setFov(75)
        base.camLens.setNear(0.8)

        # Mouse controls
        self.mouseNode = CollisionNode('mouseRay')
        self.mouseNodeNP = camera.attachNewNode(self.mouseNode)
        self.mouseNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
        self.mouseRay = CollisionRay()
        self.mouseNode.addSolid(self.mouseRay)
        self.mouseRayHandler = CollisionHandlerQueue()

        # Collision Traverser
        self.traverser = CollisionTraverser("Player Traverser")
        base.cTrav = self.traverser
        self.traverser.addCollider(self.mouseNodeNP, self.mouseRayHandler)

    def run(self):
        taskMgr.add(self.move, "moveTask", priority=-4)

    def pause(self):
        taskMgr.remove("moveTask")

    def setKey(self, key, value):
        self.keyMap[key] = value

    def move(self, task):
        if not base.mouseWatcherNode.hasMouse(): return task.cont

        pointer = base.win.getPointer(0)
        mouseX = pointer.getX()
        mouseY = pointer.getY()

        if base.win.movePointer(0, self.winXhalf, self.winYhalf):
            # calculate the looking up/down of the camera.
            # NOTE: for first person shooter, the camera here can be replaced
            # with a controlable joint of the player model
            p = camera.getP() - (mouseY - self.winYhalf) * self.mouseSpeedY
            if p <-80:
                p = -80
            elif p > 90:
                p = 90
            camera.setP(p)

            # rotate the player's heading according to the mouse x-axis movement
            h = self.player.getH() - (mouseX - self.winXhalf) * self.mouseSpeedX
            if h <-360:
                h = 360
            elif h > 360:
                h = -360
            self.player.setH(h)

        # basic movement of the player
        if self.keyMap["left"] != 0:
            self.player.setX(self.player, self.moveSpeed * globalClock.getDt())
        if self.keyMap["right"] != 0:
            self.player.setX(self.player, -self.moveSpeed * globalClock.getDt())
        if self.keyMap["forward"] != 0:
            self.player.setY(self.player, -self.moveSpeed * globalClock.getDt())
        if self.keyMap["backward"] != 0:
            self.player.setY(self.player, self.moveSpeed * globalClock.getDt())


        # keep the player on the ground
        elevation = self.main.t.terrain.getElevation(self.player.getX(), self.player.getY())
        self.player.setZ(elevation*self.main.t.zScale)

        return task.cont

    def toggleInventory(self):
        if self.inventoryActive:
            self.inventoryGui.hide()
            self.inventoryActive = False
            self.run()
        else:
            self.inventoryGui.show()
            self.inventoryActive = True
            self.pause()

    def toggleCraftInventory(self):
        if self.inventoryActive:
            self.craftInventory.hide()
            self.inventoryActive = False
            self.run()
        else:
            self.craftInventory.updateList(self.inventory)
            self.craftInventory.show()
            self.inventoryActive = True
            self.pause()

    def handleLeftMouse(self):
        # Do the mining
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            self.mouseRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())

            self.traverser.traverse(render)
            # Assume for simplicity's sake that myHandler is a CollisionHandlerQueue.
            if self.mouseRayHandler.getNumEntries() > 0:
            # This is so we get the closest object.
                self.mouseRayHandler.sortEntries()
                pickedObj = self.mouseRayHandler.getEntry(0).getIntoNodePath()

                # Range check
                if (self.player.getPos() - pickedObj.getPos(render)).length() <= 3.0:
                    self.mine(pickedObj)
                else:
                    print "You are to far, move closer!"


    def mine(self, _nodeNP):
        self.nodeNP = _nodeNP

        # get the object class
        for node in self.main.nodeGen.currentNodes:
            if self.main.nodeGen.currentNodes[node] in self.inventory:
                print "new Loot:", self.main.nodeGen.currentNodes[node].giveLoot()
                self.inventory.append(self.main.nodeGen.currentNodes[node])
                if self.main.nodeGen.currentNodes[node].lootLeft == 0:
                    self.main.nodeGen.currentNodes[node].removeModel()
                    break
                break


            # if mining node
            else:

                if self.main.nodeGen.currentNodes[node].model and self.main.nodeGen.currentNodes[node].model.getPos() == self.nodeNP.getPos(render):
                    #self.main.nodeGen.currentNodes[node].removeModel()
                    self.inventory.append(self.main.nodeGen.currentNodes[node])
                    self.currentInventoryWeight += self.main.nodeGen.currentNodes[node].weight
                    self.inventoryGui.updateList(self.inventory)
                    print "You received:", self.main.nodeGen.currentNodes[node].giveLoot(), self.main.nodeGen.currentNodes[node].giveType(), "Ores"
                    print "Inventory:", self.inventory
                    print "Current Weight:", self.currentInventoryWeight
                    break

        print self.player.getPos()
class CogdoFlyingLevel(DirectObject):
    notify = directNotify.newCategory('CogdoFlyingLevel')

    def __init__(self, parent, frameModel, startPlatformModel,
                 endPlatformModel, quadLengthUnits, quadVisibilityAhead,
                 quadVisibiltyBehind):
        self.parent = parent
        self.quadLengthUnits = quadLengthUnits
        self._halfQuadLengthUnits = quadLengthUnits / 2.0
        self.quadVisibiltyAhead = quadVisibilityAhead
        self.quadVisibiltyBehind = quadVisibiltyBehind
        self._frameModel = frameModel
        self.root = NodePath('CogdoFlyingLevel')
        self.quadrantRoot = NodePath('QuadrantsRoot')
        self.quadrantRoot.reparentTo(self.root)
        self._startPlatformModel = startPlatformModel
        self._startPlatformModel.reparentTo(self.root)
        self._startPlatformModel.setZ(Globals.Level.StartPlatformHeight)
        self._endPlatformModel = endPlatformModel
        self._endPlatformModel.reparentTo(self.root)
        self._endPlatformModel.setZ(Globals.Level.EndPlatformHeight)
        self.wallR = self._frameModel.find('**/wallR')
        self.wallL = self._frameModel.find('**/wallL')
        self._exit = CogdoGameExit()
        self._exit.reparentTo(self._endPlatformModel)
        loc = self._endPlatformModel.find('**/exit_loc')
        offset = loc.getPos(render)
        self._exit.setPos(render, offset)
        self.quadrants = []
        self.visibleQuadIndices = []
        self._numQuads = 0
        self._currentQuadNum = -1
        self._camera = None
        self._initCollisions()
        self.upLimit = self._frameModel.find('**/limit_up').getZ(render)
        self.downLimit = self._frameModel.find('**/limit_down').getZ(render)
        self.leftLimit = self._frameModel.find('**/limit_left').getX(
            render) - 30.0
        self.rightLimit = self._frameModel.find('**/limit_right').getX(
            render) + 30.0
        self.backLimit = -self.quadLengthUnits
        self.forwardLimit = self.quadLengthUnits * 20
        self._frameModel.flattenStrong()
        self.gatherableFactory = CogdoFlyingGatherableFactory()
        self.obstacleFactory = CogdoFlyingObstacleFactory()
        return

    def getExit(self):
        return self._exit

    def getBounds(self):
        return ((self.leftLimit, self.rightLimit),
                (self.backLimit, self.forwardLimit), (self.downLimit,
                                                      self.upLimit))

    def getGatherable(self, serialNum):
        for quadrant in self.quadrants:
            for gatherable in quadrant.gatherables:
                if gatherable.serialNum == serialNum:
                    return gatherable

        return

    def ready(self):
        self.gatherableFactory.destroy()
        del self.gatherableFactory
        self.obstacleFactory.destroy()
        del self.obstacleFactory
        self._initStartEndPlatforms()
        self._frameModel.reparentTo(self.root)
        self.root.reparentTo(self.parent)
        self.root.stash()

    def _initStartEndPlatforms(self):
        self.startPlatform = CogdoFlyingPlatform(
            self._startPlatformModel,
            Globals.Level.PlatformTypes.StartPlatform)
        self.endPlatform = CogdoFlyingPlatform(
            self._endPlatformModel, Globals.Level.PlatformTypes.EndPlatform)
        self._endPlatformModel.setY(self.convertQuadNumToY(self._numQuads))
        self.backLimit = self._startPlatformModel.getY(
            render) - Globals.Level.StartPlatformLength * 0.7
        self.forwardLimit = self._endPlatformModel.getY(
            render) + Globals.Level.EndPlatformLength * 0.7

    def _initCollisions(self):
        self.collPlane = CollisionPlane(
            Plane(Vec3(0, 0, 1.0), Point3(0, 0, 10)))
        self.collPlane.setTangible(0)
        self.collNode = CollisionNode('fogPlane')
        self.collNode.setIntoCollideMask(OTPGlobals.FloorBitmask)
        self.collNode.addSolid(self.collPlane)
        self.collNodePath = self.root.attachNewNode(self.collNode)
        self.collNodePath.hide()

    def destroy(self):
        del self.collPlane
        self.collNodePath.removeNode()
        del self.collNodePath
        del self.collNode
        for quadrant in self.quadrants:
            quadrant.destroy()

        self._exit.destroy()
        del self._exit
        self.root.removeNode()
        del self.root

    def onstage(self):
        self.root.unstash()
        self.update(0.0)

    def offstage(self):
        self.root.stash()

    def start(self, startTime=0.0):
        self._startTime = startTime

    def stop(self):
        pass

    def getLength(self):
        return self.quadLengthUnits * self.getNumQuadrants()

    def appendQuadrant(self, model):
        quadrant = CogdoFlyingLevelQuadrant(self._numQuads, model, self,
                                            self.root)
        if self._numQuads == 0:
            quadrant.generateGatherables(self._startPlatformModel)
        quadrant.offstage()
        self.quadrants.append(quadrant)
        self._numQuads = len(self.quadrants)

    def getNumQuadrants(self):
        return self._numQuads

    def setCamera(self, camera):
        self._camera = camera

    def getCameraActualQuadrant(self):
        camY = self._camera.getY(render)
        y = self.root.getY(render)
        return self.convertYToQuadNum(camY - y)

    def update(self, dt=0.0):
        if self._camera is None:
            return
        else:
            quadNum = clamp(self.getCameraActualQuadrant(), 0,
                            self._numQuads - 1)
            if quadNum < self._numQuads:
                self.quadrants[quadNum].update(dt)
                if quadNum + 1 < self._numQuads:
                    self.quadrants[(quadNum + 1)].update(dt)
                if quadNum != self._currentQuadNum:
                    self._switchToQuadrant(quadNum)
            return

    def _switchToQuadrant(self, quadNum):
        self.visibleQuadIndices = []
        if quadNum >= 0:
            if quadNum > 0:
                self.quadrants[max(quadNum - self.quadVisibiltyBehind,
                                   0)].onstage()
            for i in xrange(
                    quadNum,
                    min(quadNum + self.quadVisibiltyAhead + 1,
                        self._numQuads)):
                self.quadrants[i].onstage()
                self.visibleQuadIndices.append(i)
                if i == 0:
                    self.startPlatform.onstage()
                elif i == self._numQuads - 1:
                    self.endPlatform.onstage()

        self._currentQuadNum = quadNum
        for i in range(
                0, max(
                    self._currentQuadNum - self.quadVisibiltyBehind,
                    0)) + range(
                        min(self._currentQuadNum + self.quadVisibiltyAhead + 1,
                            self._numQuads), self._numQuads):
            self.quadrants[i].offstage()
            if i == 0:
                self.startPlatform.offstage()
            elif i == self._numQuads - 1:
                self.endPlatform.offstage()

    def convertQuadNumToY(self, quadNum):
        return quadNum * self.quadLengthUnits

    def convertYToQuadNum(self, y):
        return int(y / self.quadLengthUnits)

    def convertCenterYToQuadNum(self, y):
        return self.convertYToQuadNum(y + self._halfQuadLengthUnits)
class Water(AssetBase):
    def __init__(self, name, size=10000, resolution=1024):
        """Arguments:
        size -- Edge length of the water square.
        resolution -- Texture size of the rendered reflection buffer.
        """
        # Uncomment to see the output of the refclection buffer.
        base.bufferViewer.toggleEnable()

        AssetBase.__init__(self)
        self.name = name

        self.cm = CardMaker("water surface")
        self.cm.setFrame(-0.5 * size, 0.5 * size, -0.5 * size, 0.5 * size)
        self.cm.setHasUvs(True)
        self.node = NodePath(self.cm.generate())

        self.node.setP(self.node, -90)
        self.node.flattenLight()
        self.node.hide(BitMask32.bit(1))
        # self.node.setTwoSided(True)
        self.node.setShaderOff()

        # size of one texture tile in meters
        self.tex_size = 100.0

        diffuse = TexturePool.loadTexture("textures/water.diffuse.png")
        diffuse.setWrapU(Texture.WMRepeat)
        diffuse.setWrapV(Texture.WMRepeat)
        diffuse.setMinfilter(Texture.FTLinearMipmapLinear)
        diffuse.setMagfilter(Texture.FTLinearMipmapLinear)
        self.diffuse_stage = TextureStage("diffuse")
        self.diffuse_stage.setSort(2)
        self.node.setTexture(self.diffuse_stage, diffuse)
        self.node.setTexScale(self.diffuse_stage, size / self.tex_size, size / self.tex_size)

        # Reflection camera renders to 'buffer' which is projected onto the
        # water surface.
        buffer = base.win.makeTextureBuffer("water reflection", resolution, resolution)
        buffer.setClearColor(Vec4(0, 0, 0, 1))

        self.refl_cam = base.makeCamera(buffer)
        self.refl_cam.reparentTo(self.node)
        self.refl_cam.node().setCameraMask(BitMask32.bit(1))
        self.refl_cam.node().getLens().setFov(base.camLens.getFov())
        self.refl_cam.node().getLens().setNearFar(1, 100000)

        plane = PlaneNode("water culling plane", Plane(Vec3(0, 0, 1), Point3(0, 0, 0)))
        cfa = CullFaceAttrib.makeReverse()
        cpa = ClipPlaneAttrib.make(PlaneNode.CEVisible, plane)
        rs = RenderState.make(cfa, cpa)
        self.refl_cam.node().setInitialState(rs)

        reflection = buffer.getTexture()
        reflection.setMinfilter(Texture.FTLinear)
        reflection.setMagfilter(Texture.FTLinear)
        self.refl_stage = TextureStage("reflection")
        self.refl_stage.setSort(1)
        self.node.projectTexture(self.refl_stage, reflection, base.cam)
        self.node.setTexture(self.refl_stage, reflection)

        # Blend between diffuse and reflection.
        self.diffuse_stage.setColor(VBase4(1, 1, 1, 0.2))  # opacity of 20%
        self.diffuse_stage.setCombineRgb(
            TextureStage.CMInterpolate,
            TextureStage.CSTexture,
            TextureStage.COSrcColor,
            TextureStage.CSPrevious,
            TextureStage.COSrcColor,
            TextureStage.CSConstant,
            TextureStage.COSrcAlpha,
        )

        self.addTask(self.update, name="water update", sort=1, taskChain="world")

    def update(self, task):
        """Updates position of the reflection camera and the water plane."""
        mc = base.cam.getMat(render)
        # mf = Plane(Vec3(0, 0, 1), Point3(0, 0, 0)).getReflectionMat()
        mf = Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)
        self.refl_cam.setMat(mc * mf)

        self.node.setX(camera.getX(render))
        self.node.setY(camera.getY(render))
        self.node.setTexOffset(self.diffuse_stage, self.node.getX() / self.tex_size, self.node.getY() / self.tex_size)

        return task.cont

    def destroy(self):
        self.removeAllTasks()
        self.node.removeNode()
        self.refl_cam.removeNode()
Exemple #8
0
class Water(AssetBase):
    def __init__(self, name, size=10000, resolution=1024):
        """Arguments:
        size -- Edge length of the water square.
        resolution -- Texture size of the rendered reflection buffer.
        """
        # Uncomment to see the output of the refclection buffer.
        base.bufferViewer.toggleEnable()

        AssetBase.__init__(self)
        self.name = name

        self.cm = CardMaker("water surface")
        self.cm.setFrame(-0.5 * size, 0.5 * size, -0.5 * size, 0.5 * size)
        self.cm.setHasUvs(True)
        self.node = NodePath(self.cm.generate())

        self.node.setP(self.node, -90)
        self.node.flattenLight()
        self.node.hide(BitMask32.bit(1))
        #self.node.setTwoSided(True)
        self.node.setShaderOff()

        # size of one texture tile in meters
        self.tex_size = 100.0

        diffuse = TexturePool.loadTexture("textures/water.diffuse.png")
        diffuse.setWrapU(Texture.WMRepeat)
        diffuse.setWrapV(Texture.WMRepeat)
        diffuse.setMinfilter(Texture.FTLinearMipmapLinear)
        diffuse.setMagfilter(Texture.FTLinearMipmapLinear)
        self.diffuse_stage = TextureStage("diffuse")
        self.diffuse_stage.setSort(2)
        self.node.setTexture(self.diffuse_stage, diffuse)
        self.node.setTexScale(self.diffuse_stage, size / self.tex_size,
                              size / self.tex_size)

        # Reflection camera renders to 'buffer' which is projected onto the
        # water surface.
        buffer = base.win.makeTextureBuffer("water reflection", resolution,
                                            resolution)
        buffer.setClearColor(Vec4(0, 0, 0, 1))

        self.refl_cam = base.makeCamera(buffer)
        self.refl_cam.reparentTo(self.node)
        self.refl_cam.node().setCameraMask(BitMask32.bit(1))
        self.refl_cam.node().getLens().setFov(base.camLens.getFov())
        self.refl_cam.node().getLens().setNearFar(1, 100000)

        plane = PlaneNode("water culling plane",
                          Plane(Vec3(0, 0, 1), Point3(0, 0, 0)))
        cfa = CullFaceAttrib.makeReverse()
        cpa = ClipPlaneAttrib.make(PlaneNode.CEVisible, plane)
        rs = RenderState.make(cfa, cpa)
        self.refl_cam.node().setInitialState(rs)

        reflection = buffer.getTexture()
        reflection.setMinfilter(Texture.FTLinear)
        reflection.setMagfilter(Texture.FTLinear)
        self.refl_stage = TextureStage("reflection")
        self.refl_stage.setSort(1)
        self.node.projectTexture(self.refl_stage, reflection, base.cam)
        self.node.setTexture(self.refl_stage, reflection)

        # Blend between diffuse and reflection.
        self.diffuse_stage.setColor(VBase4(1, 1, 1, 0.2))  # opacity of 20%
        self.diffuse_stage.setCombineRgb(
            TextureStage.CMInterpolate, TextureStage.CSTexture,
            TextureStage.COSrcColor, TextureStage.CSPrevious,
            TextureStage.COSrcColor, TextureStage.CSConstant,
            TextureStage.COSrcAlpha)

        self.addTask(self.update,
                     name="water update",
                     sort=1,
                     taskChain="world")

    def update(self, task):
        """Updates position of the reflection camera and the water plane."""
        mc = base.cam.getMat(render)
        #mf = Plane(Vec3(0, 0, 1), Point3(0, 0, 0)).getReflectionMat()
        mf = Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)
        self.refl_cam.setMat(mc * mf)

        self.node.setX(camera.getX(render))
        self.node.setY(camera.getY(render))
        self.node.setTexOffset(self.diffuse_stage,
                               self.node.getX() / self.tex_size,
                               self.node.getY() / self.tex_size)

        return task.cont

    def destroy(self):
        self.removeAllTasks()
        self.node.removeNode()
        self.refl_cam.removeNode()
Exemple #9
0
class Army(GameObject):
    def __init__(self, player, name, x, y, soldiers, general=None):
        global army_count
        self.my_id = army_count
        army_count += 1

        print "ARMY ID IS", self.my_id

        self.name = name
        self.x = x
        self.y = y
        self.target_x = x
        self.target_y = y
        self.scale = counter_scale
        self.range = 50.0

        self.selected = False

        self.general = general
        self.soldiers = soldiers
        self.state = "normal"
        self.speed = 25.0

        self.battle = -1

        self.stat_init = 0.0
        self.stat_hit = 0.0
        self.stat_block = 0.0
        self.stat_delay = 0.0

        self.player = player
        if self.player == 0:
            self.colour = (0.5, 0.5, 0.5, 1)
            self.model = loader.loadModel("models/infantry_counter_grey.egg")
        if self.player == 1:
            self.colour = (1, 0, 0, 1)
            self.model = loader.loadModel("models/infantry_counter_red.egg")
        elif self.player == 2:
            self.colour = (0, 1, 0, 1)
            self.model = loader.loadModel("models/infantry_counter_green.egg")

        self.node_path = NodePath("army" + str(self.my_id) + "_node_path")
        self.model.reparentTo(self.node_path)
        self.node_path.setPos(x, y, 0)
        self.node_path.setTag("player", str(player))
        self.node_path.setScale(self.scale, self.scale, self.scale)

        self.node_col = self.node_path.attachNewNode(
            CollisionNode("army" + str(self.my_id) + "_c_node"))
        self.node_col.setScale((1, 1, 0.5))
        self.node_col.setPos(0, 0, 0)
        self.node_col.node().addSolid(CollisionSphere(0, 0, 0, 1))
        self.node_col.setTag("type", "army")
        base.cTrav.addCollider(self.node_col, base.col_manager.col_handler)
        #self.node_col.show()
        self.node_path.setTag("id", str(self.my_id))
        self.army_fight_col = self.node_path.attachNewNode(
            CollisionNode("army" + str(self.my_id) + "_batcol_node"))
        self.army_fight_col.setScale((2, 2, 0.5))
        self.army_fight_col.setPos(0, 0, 0)
        self.army_fight_col.node().addSolid(CollisionSphere(0, 0, 0, 1))
        self.army_fight_col.setColor(1, 0, 0, 0.1)
        self.army_fight_col.setTag("player", str(player))
        self.army_fight_col.setTag("state", "normal")
        self.army_fight_col.setTag("type", "army")
        base.cTrav.addCollider(self.army_fight_col,
                               base.col_manager.col_handler)
        #self.army_fight_col.show()

        self.selection_ring = self.selection_ring_create(size=1.2)
        self.selection_ring.reparentTo(self.node_path)
        self.selection_ring.hide()

        self.node_path.reparentTo(render)

    def turn_start(self):
        rate = 0.5
        army_scl_up = self.model.scaleInterval(rate, Point3(1.5, 1.5, 1.5))
        army_scl_down = self.model.scaleInterval(rate, Point3(1, 1, 1))
        self.sq_army_bat = Sequence(army_scl_up, army_scl_down)
        self.sq_army_bat.loop()

    def turn_end(self):
        try:
            self.sq_army_bat.finish()
        except:
            print "no sequence to end"

    def die(self):
        if base.single_player == False and base.client == False:
            base.net_manager.server_messager("army_kill", [self.my_id])
        self.state = "dead"
        self.army_fight_col.removeNode()
        self.node_col.removeNode()
        rate = 4
        intvl_shrink = self.model.scaleInterval(rate, Point3(0, 0, 0))
        func_destroy = Func(self.destroy)
        self.sq_die = Sequence(intvl_shrink, func_destroy)
        self.sq_die.start()
        base.battles[self.battle].recenter()
        base.battles[self.battle].shrink()
        if self.selected:
            i = base.col_manager.selecteds.index(self)
            del base.col_manager.selecteds[i]

    def stop(self):
        try:
            self.sq_army_move.pause()
        except:
            print "already stopped"

    def move_to_point(self, tx, ty):
        self.target_x = tx
        self.target_y = ty
        dist = float(
            TCalc.dist_to_point(self.node_path.getX(), self.node_path.getY(),
                                tx, ty))
        print dist
        #time = dist/speed
        #print dist/speed
        #print time*speed,dist
        try:
            self.sq_army_move.pause()
            self.intvl_army_move = None
        except:
            print "no sequence"

        if dist > 1:
            self.intvl_army_move = self.node_path.posInterval(
                dist / self.speed,
                Point3(self.target_x, self.target_y, 0),
                startPos=Point3(self.node_path.getX(), self.node_path.getY(),
                                0))
            self.sq_army_move = Sequence(self.intvl_army_move)
            self.sq_army_move.start()
        else:
            try:
                self.sq_army_move.finish()
            except:
                print "no sequence"

    def set_target(self, sender, tx, ty):
        if self.state == "normal":
            if base.single_player == False:
                base.net_manager.army_move(self.my_id, tx, ty)
            else:
                self.move_to_point(tx, ty)

    def battle_shuffle(self, tx, ty):
        if base.single_player == False:
            base.net_manager.army_move(self.my_id, tx, ty)
        else:
            self.move_to_point(tx, ty)
Exemple #10
0
class Main(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        self.key = {
            "left": 0,
            "right": 0,
            "forward": 0,
            "backward": 0,
            "cam_left": 0,
            "cam_right": 0,
            "cam_down": 0,
            "cam_up": 0,
            "up": 0,
            "down": 0
        }

        #####################
        #
        #   Simply testing procedural cave generation
        #
        #####################
        self.start = PlatformSeg(LVector3(0, 0, 0))
        self.start.generateAllParts(render)
        self.lostWood = LostWood(
            LVector3(self.start.pos.x + 750,
                     self.start.parts[0].pos.y + self.start.parts[0].wid,
                     self.start.pos.z))
        self.lostWood.generateAllParts(render)
        self.cave = Cave(
            LVector3(self.lostWood.pos.x + 1100,
                     self.lostWood.parts[6].pos.y + self.lostWood.parts[6].wid,
                     self.lostWood.pos.z))
        self.cave.generateAllParts(render)
        self.end = End(
            LVector3(
                self.cave.thirdRoomParts[8].pos.x - 200,
                self.cave.thirdRoomParts[8].pos.y +
                self.cave.thirdRoomParts[8].wid,
                self.cave.thirdRoomParts[8].pos.z))
        self.end.generate(render)

        ####################
        #
        #   Setting light so that we could see the definition in the walls
        #
        ####################

        render.setShaderAuto()
        self.dlight = DirectionalLight('dlight')
        self.dlight.setColor(LVector4(0.3, 0.1, 0.7, 1))
        dlnp = render.attachNewNode(self.dlight)
        dlnp.setHpr(90, 20, 0)
        render.setLight(dlnp)

        self.alight = render.attachNewNode(AmbientLight("Ambient"))
        self.alight.node().setColor(LVector4(0.5, 0.5, 1, .1))
        render.setLight(self.alight)

        base.disableMouse()
        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(render)
        base.camera.reparentTo(self.floater)
        base.camera.setPos(0, -20, 500)
        base.camera.setP(-50)
        self.bindKeys()

    def setKey(self, key, value):
        self.key[key] = value

    def bindKeys(self):
        self.accept("escape", sys.exit)
        self.accept("a", self.setKey, ["left", True])
        self.accept("a-up", self.setKey, ["left", False])
        self.accept("d", self.setKey, ["right", True])
        self.accept("d-up", self.setKey, ["right", False])
        self.accept("w", self.setKey, ["forward", True])
        self.accept("w-up", self.setKey, ["forward", False])
        self.accept("s", self.setKey, ["backward", True])
        self.accept("s-up", self.setKey, ["backward", False])
        self.accept("space", self.setKey, ["down", True])
        self.accept("space-up", self.setKey, ["down", False])
        self.accept("shift", self.setKey, ["up", True])
        self.accept("shift-up", self.setKey, ["up", False])
        self.accept("arrow_up", self.setKey, ["cam_up", True])
        self.accept("arrow_up-up", self.setKey, ["cam_up", False])
        self.accept("arrow_down", self.setKey, ["cam_down", True])
        self.accept("arrow_down-up", self.setKey, ["cam_down", False])
        self.accept("arrow_left", self.setKey, ["cam_left", True])
        self.accept("arrow_left-up", self.setKey, ["cam_left", False])
        self.accept("arrow_right", self.setKey, ["cam_right", True])
        self.accept("arrow_right-up", self.setKey, ["cam_right", False])

        taskMgr.add(self.update, "update")

    def update(self, task):
        delta = globalClock.getDt()
        WALKSPEED = 300
        SPEED = 100
        if self.key["left"]:
            self.floater.setX(self.floater.getX() - WALKSPEED * delta)
        if self.key["right"]:
            self.floater.setX(self.floater.getX() + WALKSPEED * delta)
        if self.key["forward"]:
            self.floater.setY(self.floater.getY() + WALKSPEED * delta)
        if self.key["backward"]:
            self.floater.setY(self.floater.getY() - WALKSPEED * delta)
        if self.key["up"]:
            self.floater.setZ(self.floater.getZ() + WALKSPEED * delta)
        if self.key["down"]:
            self.floater.setZ(self.floater.getZ() - WALKSPEED * delta)

        if self.key["cam_left"]:
            base.camera.setH(base.camera.getH() + SPEED * delta)
        if self.key["cam_right"]:
            base.camera.setH(base.camera.getH() - SPEED * delta)
        if self.key["cam_up"]:
            base.camera.setP(base.camera.getP() + SPEED * delta)
        if self.key["cam_down"]:
            base.camera.setP(base.camera.getP() - SPEED * delta)

        ######################
        #
        # SIMPLE OCCLUSION FOR START AREA
        #
        ######################

        for p in self.start.parts:
            if p.type == 'IceCube':
                if math.fabs(
                    (math.sqrt((p.model.getX() * p.model.getX()) +
                               (p.model.getY() * p.model.getY())) -
                     math.sqrt(
                         (self.floater.getX() * self.floater.getX()) +
                         (self.floater.getY() * self.floater.getY())))) <= 400:
                    p.show()
                    #Ice cube movement
                    p.bob(delta)
                else:
                    p.hide()

            if p.type == 'Prism':
                if p.type == 'Prism':
                    if math.fabs(
                        (math.sqrt((p.pos.x * p.pos.x) + (p.pos.y * p.pos.y)) -
                         math.sqrt(
                             (self.floater.getX() * self.floater.getX()) +
                             (self.floater.getY() * self.floater.getY()))
                         )) <= 1000:
                        p.show()
                    else:
                        p.hide()

        ######################
        #
        # SIMPLE OCCLUSION FOR CAVE PARTS
        #
        ######################
        for p in self.cave.parts:
            if p.type == 'Prism':
                if math.fabs(
                    (math.sqrt((p.pos.x * p.pos.x) + (p.pos.y * p.pos.y)) -
                     math.sqrt((self.floater.getX() * self.floater.getX()) +
                               (self.floater.getY() * self.floater.getY()))
                     )) <= 2200:
                    p.show()
                else:
                    p.hide()

            if p.type == 'IceCube':
                if math.fabs(
                    (math.sqrt((p.model.getX() * p.model.getX()) +
                               (p.model.getY() * p.model.getY())) -
                     math.sqrt((self.floater.getX() * self.floater.getX()) +
                               (self.floater.getY() * self.floater.getY()))
                     )) <= 1250:
                    p.show()

                    #Ice cube movement
                    self.cave.moveIceCubes(delta / 25)
                    for p in self.cave.iceCubesThirdRoom:
                        p.bob(delta / 25)
                    for p in self.cave.iceCubesSecondRoom:
                        p.bob(delta / 25)
                    self.cave.bigCube.bob(delta / 25)

                    for p in self.start.iceCubes:
                        p.bob(delta)
                else:
                    p.hide()

        return task.cont
class KVProjectile(DirectObject):
    
    #Property stuff
    creaTime = time.clock()
    dur = 1
    vec = 0
    delta = .5
    prevtime = 0
    flag = False
    
    #defining the thing fired by whatever gun we have
    def __init__(self, camera, look, id):
        
        #nodepath of the projectile, give it a trajectory
        self.projectileNode = NodePath('projectile'+str(id))
        self.projectileNode.reparentTo(render)
        
        #by passing the camera node form the camMov object, all projectiles are spawned 5 units in front of the camera
        self.projectileNode.setHpr(look, 0, 0, 0)
        self.projectileNode.setPos(camera,0,3, 3)
        
        #fix z position to line up with gun
        self.projectileNode.setScale(.1)
        self.projectileModel = loader.loadModel("./resources/beam.egg")
        self.projectileModel.reparentTo(self.projectileNode)
    	
        #must calculate unit vector based on direction
        dir = render.getRelativeVector(look, Vec3(0, 1, 0))
    	
        #speed up or slow down projectiles here
        dir = dir*5
        self.vec = dir
        
        #base.cTrav = CollisionTraverser()
        cs = CollisionSphere(0, 0, 0, 2.5)
        cnodepath = self.projectileNode.attachNewNode(CollisionNode('projNode'))
        cnodepath.node().addSolid(cs)
        self.collHand = CollisionHandlerEvent()
        self.collHand.addInPattern('into'+str(id))
        self.collHand.addOutPattern('outof')
        
        #cTrav has the distinction of global colider handler
        base.cTrav.addCollider(cnodepath, self.collHand)
        self.acceptOnce('into'+str(id), self.hit)
      
	    #deal with colliding or special effects here.
	    #wanted projectiles to be short lived
	    #so i will make them delete themselves after impact or time expired
        #writing a task that will rek the projectiles at the end of time
        self.damage = 5
    def moveTask(self, task):
        
        #curtime = time.clock()
        #self.delta = curtime-self.prevtime
        
        if self.flag:
            return task.done
        
        velx = self.vec.x*self.delta
        vely = self.vec.y*self.delta
        velz = self.vec.z*self.delta
        x = self.projectileNode.getX()
        y = self.projectileNode.getY()
        z = self.projectileNode.getZ()
        self.projectileNode.setPos(x+velx, y+vely, z+velz)
        #prevtime = time.clock()
            
        
        if task.time < self.dur:
        
            return task.cont
        else:
            
            self.flag = True
            return task.done
        

    def hit(self, collEntry):
        
        #throw out a custom message for what hit
        if collEntry.getIntoNodePath().getName() != 'projNode':
           
            temp = collEntry.getIntoNodePath().getName()
            messenger.send(temp, [self.damage]) 
            #remove the impacting projectile
            collEntry.getFromNodePath().getParent().getParent().removeNode()
            self.flag =  True
            del self
class ChargeProjectile(DirectObject):
    
    dur = 2
    delta = .15
    flag = False
    
    def __init__(self, spawn, taregt, id):
        
        self.projectileNode = NodePath('projectile'+str(id))
        self.projectileNode.reparentTo(render)

        self.projectileNode.setPos(spawn,0,-10, 0)
        self.projectileNode.setScale(1.5)
        self.projectileModel = Actor("./resources/sphereShot",{"grow":"./resources/sphereShot-grow"})
        self.projectileModel.setColorScale(200, 0, 255, 100)
        self.projectileModel.reparentTo(self.projectileNode)
        self.projectileNode.setHpr(spawn, 0, 0, 0)


        dir = render.getRelativeVector(spawn, Vec3(0, 1, 0))
        self.vec = dir*-100
        cs = CollisionSphere(0, 0, 0, 2.5)
        cnodepath = self.projectileNode.attachNewNode(CollisionNode('projNode'))
        cnodepath.node().addSolid(cs)
        self.collHand = CollisionHandlerEvent()
        self.collHand.addInPattern('bossProjectileinto'+str(id))
        self.collHand.addOutPattern('outof')
        base.cTrav.addCollider(cnodepath, self.collHand)
        self.acceptOnce('bossProjectileinto'+str(id), self.hit)
        self.damage = 15


    def moveTask(self, task):    
        
        if self.flag:
            return task.done
        
        velx = self.vec.x*self.delta
        vely = self.vec.y*self.delta
        velz = self.vec.z*self.delta
        x = self.projectileNode.getX()
        y = self.projectileNode.getY()
        z = self.projectileNode.getZ()
        self.projectileNode.setPos(x+velx, y+vely, z+velz)

        if task.time < self.dur:
        
            return task.cont
        else:
            
            self.flag = True
            return task.done

    def hit(self, collEntry):
        
        #throw out a custom message for what hit
        if collEntry.getIntoNodePath().getName() != 'projNode':
           
            temp = collEntry.getIntoNodePath().getName()
            print temp
            messenger.send(temp, [self.damage]) 
            
            #remove the impacting projectile
            collEntry.getFromNodePath().getParent().getParent().removeNode()
            self.flag =  True
            del self

    def wait(self, task):

        if task.time > 2.24:
            return task.done
	    
        return task.cont
Exemple #13
0
class Ship: 
    set = 0
    fuel = 1
    air = 1
    current = 0
    acceleration = 0.002
    max = 0.25
    fall = 0.001
    gravity = 0.3
    steer = 0
    steerspeed = 0.05
    slide = 0
    jumpheight = 0.2
    jump = True
    control = True
    dead = False
    under = None

    def __init__(self, root, model):
        self.root = root
        self.node = NodePath("ship")
        self.model = model
        self.model.reparentTo(self.node)
        self.node.reparentTo(render)
        self.setColliders()

        self.explosion = loader.loadModel("assets/models/explosion.bam")
        self.explosion.reparentTo(render)
        self.explosion.hide()
        self.explosion.setLightOff()

        self.loadAudio()

    def loadAudio(self): # each ship has their own set of sounds
        folder = "assets/audio/sfx/"
        self.audio = {
            "bounce":loader.loadSfx(folder+"bounce.wav"),
            "engine":loader.loadSfx(folder+"engine.wav"),
            "explode":loader.loadSfx(folder+"explode.wav"),
            "land":loader.loadSfx(folder+"land.wav"),
            "pickup":loader.loadSfx(folder+"pickup.wav"),
            "shave":loader.loadSfx(folder+"shave.wav"),
        }
        
    def setColliders(self):
        self.handlers = []
        for i in range(3):
            if i == 1: y = 0.2
            else: y = -0.2
            h = colRay(self.node, ((-1+i)/4, y, .1))
            self.handlers.append(h)
        self.colNose = colSpheres(self.node, 
            [((0,.1,.1),.02)])
        self.colLeft = colSpheres(self.node, 
            [((-.15,-.1,.2), .1)])
        self.colRight = colSpheres(self.node, 
            [((.15,-.1,.2), .1)])
        self.colTop = colSpheres(self.node,
            [((0,0.2,0.4), .1)])

    def update(self):
        self.control = True
        self.air -= (1/5000)*self.o2drain
        self.fuel -= (self.speed/1000)*self.fueldrain
        if self.air <= 0.01 or self.fuel <= 0.01:
            self.control = False
        
        if not self.dead:
            self.collide()
            self.specialFloor()
            # Set fw/bw speed
            self.speed = clamp(self.speed, 0, self.max)
            self.audio["engine"].setPlayRate((self.speed*7))
            # Update node position
            x = self.node.getX()+((self.steer+self.slide)*self.steerspeed)
            y = self.node.getY()+self.speed
            z = self.node.getZ()-self.fall
            self.node.setFluidPos(x, y, z)
            # Point nose to fall speed
            self.model.setP(-(self.fall*300))
            # Set flame color to speed
            cc = (self.speed*7)-uniform(0,0.3)
            self.model.getChild(0).setColorScale(cc*2,cc,cc,1)
            # Respawn if fallen off.
            if z < -20:
                self.respawn()
            self.setMeters()

    def specialFloor(self):
        f = self.under
        if f:
            if f == 1:
                self.root.road.playNextMap()
                self.respawn()
            elif f == 2:
                self.explode()
            elif f == 3:
                self.speed += self.acceleration*2
            elif f == 4:
                self.fuel = 0.99
                self.air = 0.99
            elif f == 5:
                self.control = False
            elif f == 6:
                self.speed -= self.acceleration*2
    
    def collide(self):
        if self.colNose.getNumEntries() > 0:
            if self.speed > 0.1: # full frontal crash
                self.explode()
            else: # full frontal bump
                self.audio["shave"].play()
                self.speed = 0
                self.node.setY(self.node.getY()-0.2)
        # bounce left and right
        if self.colLeft.getNumEntries() > 0:
            self.steer = 1
            self.audio["shave"].play()
        elif self.colRight.getNumEntries() > 0:
            self.steer = -1
            self.audio["shave"].play()
        # connect to floor
        self.grounded = False
        self.under = under = None
        self.root.cTrav.traverse(render)
        hits = [0,0,0]
        for h, handler in enumerate(self.handlers):
            if len(list(handler.entries)) > 0:
                handler.sortEntries()
                entry = list(handler.entries)[0]
                hitPos = entry.getSurfacePoint(render)
                distToGround =  self.node.getZ() - hitPos.getZ()
                if distToGround < 0.03:
                    hits[h] = 1
                if distToGround < self.fall+0.05:
                    if self.fall > 0.05: #go bounce
                        self.fall = -0.05
                        self.jump = True
                        self.audio["bounce"].play()
                    elif self.fall > 0: #land
                        self.fall = 0
                        self.jump = True
                        self.audio["land"].play()
                    if self.colTop.getNumEntries() >  0:
                        self.fall = 0
                    self.grounded = True
                    under = entry.getSurfacePoint(render)
                    self.node.setZ(hitPos.getZ()+0.01)
        s = self.getSteerVal()
        if hits == [1,0,0]:
            self.slide += 0.01
        elif hits == [0,0,1]:
            self.slide -= 0.01
        elif not hits == [0,0,0]:
            self.slide = 0
        # fall if not on floor
        if not self.grounded:
            self.fall += (self.gravity)/550
            if self.colTop.getNumEntries() > 0:
                if self.fall < 0:
                    self.fall = -self.fall
        # else see what color the floor is
        elif under:
            x, y, z = under
            x = round(x)
            y = round(y/2)
            z = round(z*2)-1
            try:
                color = self.root.road.map[y][x][z][1]
                if color <= 8 :
                    self.under = color
            except:
                pass

    def setMeters(self):
        self.root.hud.setSpeed(self.speed*114)
        self.root.hud.setAir(self.air*14)
        self.root.hud.setFuel(self.fuel*14)
        self.root.hud.setMiles(self.node.getY(), len(self.root.road.map))
        self.root.hud.setGravity(self.gravity)

    def explode(self):
        Explosion(self, self.explosion)
        self.audio["engine"].stop()
        self.audio["explode"].play()
        self.node.hide()
        self.dead = True

    def accelerate(self):
        if not self.dead and self.control:
            self.speed += self.acceleration

    def decelerate(self):
        if not self.dead and self.control:
            self.speed -= self.acceleration

    def getSteerVal(self):
        return ((self.speed*4)+0.1)

    def goLeft(self):
        if not self.dead and self.control:
            if self.grounded or self.fall < -0.07:
                if self.colLeft.getNumEntries() == 0:
                    self.steer = -self.getSteerVal()
                    self.slide = 0

    def goRight(self):
        if not self.dead and self.control:
            if self.grounded or self.fall < -0.07:
                if self.colRight.getNumEntries() == 0:
                    self.steer = self.getSteerVal()
                    self.slide = 0.01

    def jumpUp(self):
        if self.gravity < 8:
            if not self.dead and self.control:
                if self.colTop.getNumEntries() == 0:
                    if self.jump and self.fall < 0.05:
                        self.fall = -0.1
                        self.jump = False

    def respawn(self):
        self.audio["engine"].setLoop(True)
        self.audio["engine"].setVolume(1)
        self.audio["engine"].play()
        self.node.show()
        self.node.setPos(4,0,0.7)
        self.fall = 0
        self.speed = 0
        self.jump = True
        self.control = True
        self.dead = False
        self.air = 1
        self.fuel = 1
        self.gravity = self.root.road.gravity
        self.fueldrain = self.root.road.fueldrain
        self.o2drain = self.root.road.o2drain
        self.setMeters()
Exemple #14
0
class Maleficium(ShowBase):
    def __init__(self):
        compressedTextures = ConfigVariableString('compressed-textures','1') # Compresses Textures on load (increases loadtime / framerate)
        ShowBase.__init__(self)
        
        ## Debug Values (True/False)
        self.fpsMeter = True
        
        debug.checkDebugSettings(self)

        self.KeyBindings()

        ## Load World
        world.load('prisonCrater')

        ## Add Player to World
        self.playerBox = NodePath('player')
        self.player = Actor("data/models/hm.bam",
                            {"run":"data/models/hm-run.bam",
                             "idle":"data/models/hm.bam"})
        self.player.reparentTo(self.playerBox)
        self.player.setScale(.01)
        self.playerBox.reparentTo(render)
        self.isMoving = False

        ## Create Camera
        base.disableMouse()
        self.cameratarget = self.render.attachNewNode('Camera Target')
        base.camera.setPos(self.playerBox.getX(),self.playerBox.getY()+20,self.playerBox.getZ()+5)
        self.cameratarget.setPos(self.playerBox.getX(),self.playerBox.getY(),self.playerBox.getZ()+6)
        self.radius = 10
        self.XYAngle = .028
        self.ZAngle = .01

        ## Set Up Ground Collisions
        ## Player Collision
        base.cTrav = CollisionTraverser()
        self.ColHandler = CollisionHandlerFloor()       
        self.colGroundRay = CollisionNode('colGroundRay')
        self.colGroundRay.addSolid(CollisionRay(0,0,2,0,0,-1))
        self.playerCol = self.playerBox.attachNewNode(self.colGroundRay)
        base.cTrav.addCollider(self.playerCol,self.ColHandler)
        self.ColHandler.addCollider(self.playerCol,self.playerBox)
                                       
        ## Add main Game Loop to taskmanager
        taskMgr.add(self.gameLoop,'mainLoop')


    ### Input Structure; Coded by Darren Kent (Modeled after Roaming-Ralph by Ryan Myers)
    def KeyBindings(self):
        ## Setup Map
        self.startRightClick = True
        
        self.keyMap = {
            "forward":0,
            "backward":0,
            "turn_left":0,
            "turn_right":0,
            "strafe_left":0,
            "strafe_right":0,
            "cam_up":0,
            "cam_down":0,
            "cam_right":0,
            "cam_left":0,
            "zoom_in":0,
            "zoom_out":0,
            "right_click":0,
            "wheel_zoom_in":0,
            "wheel_zoom_out":0,
            }

        ## Accept Keys
        self.accept('escape',sys.exit)
        self.accept('w', self.setKey, ['forward',1])
        self.accept('w-up', self.setKey, ['forward',0])
        self.accept('s', self.setKey, ['backward',1])
        self.accept('s-up', self.setKey, ['backward',0])
        self.accept('a', self.setKey, ['turn_left',1])
        self.accept('a-up', self.setKey, ['turn_left',0])
        self.accept('d', self.setKey, ['turn_right',1])
        self.accept('d-up', self.setKey, ['turn_right',0])
        self.accept('q', self.setKey, ['strafe_left',1])
        self.accept('q-up', self.setKey, ['strafe_left',0])
        self.accept('e', self.setKey, ['strafe_right',1])
        self.accept('e-up', self.setKey, ['strafe_right',0])
        self.accept('arrow_up', self.setKey, ['cam_down',1])
        self.accept('arrow_up-up', self.setKey, ['cam_down',0])
        self.accept('arrow_down', self.setKey, ['cam_up',1])
        self.accept('arrow_down-up', self.setKey, ['cam_up',0])
        self.accept('arrow_right', self.setKey, ['cam_right',1])
        self.accept('arrow_right-up', self.setKey, ['cam_right',0])
        self.accept('arrow_left', self.setKey, ['cam_left',1])
        self.accept('arrow_left-up', self.setKey, ['cam_left',0])
        self.accept('[', self.setKey, ['zoom_in',1])
        self.accept('[-up', self.setKey, ['zoom_in',0])
        self.accept(']', self.setKey, ['zoom_out',1])
        self.accept(']-up', self.setKey, ['zoom_out',0])

        ## Accept Mouse
        self.accept('mouse3',self.setKey, ['right_click',1])
        self.accept('mouse3-up',self.setKey, ['right_click',0])
        self.accept('wheel_up',self.setKey, ['wheel_zoom_in',1])
        self.accept('wheel_down',self.setKey, ['wheel_zoom_out',1])

    ### Set Key Presses; Coded by Darren Kent (Modeled after Roaming-Ralph by Ryan Myers)
    def setKey(self,key,value):
        self.keyMap[key] = value        
            


    ### Main Game Loop; Coded by Darren Kent
    def gameLoop(self,task):

        ## Keyboard Camera Controls
        if (self.keyMap["cam_left"]!=0):
            self.XYAngle += .002
        if (self.keyMap["cam_right"]!=0):
            self.XYAngle -= .002
        if (self.keyMap["cam_up"] != 0):
            if self.ZAngle <= .045:
                self.ZAngle += .001
        if (self.keyMap["cam_down"] != 0):
            if self.ZAngle >= .002:
                self.ZAngle -= .001
        if (self.keyMap["zoom_in"] != 0):
            if self.radius >= 4:
                self.radius -= 1
                self.setRadius = self.radius
        if (self.keyMap["zoom_out"] != 0):
            if self.radius <= 40:
                self.radius += 1
                self.setRadius = self.radius
                
        ## Mouse Camera Controls
        if (self.keyMap["right_click"]!=0):
            if self.startRightClick == True:
                self.startRightClick = False
                self.tempMouseX = base.mouseWatcherNode.getMouseX()
                self.tempMouseY = base.mouseWatcherNode.getMouseY()
                self.tempXAngle = self.XYAngle
                self.tempZAngle = self.ZAngle
                self.tempPlayerH = self.playerBox.getH()
            elif self.startRightClick == False:
                Ztemp = self.tempZAngle + (base.mouseWatcherNode.getMouseY() - self.tempMouseY) / 20
                self.XYAngle = self.tempXAngle - (base.mouseWatcherNode.getMouseX() - self.tempMouseX) / 20
                if Ztemp >= .045:
                    Ztemp = .045
                if Ztemp <= 0.002:
                    Ztemp = 0.002
                self.ZAngle = Ztemp
        else:
            self.startRightClick = True
       
        if (self.keyMap["wheel_zoom_in"] != 0):
            if self.radius >= 7:
                self.radius -= 3
                self.setRadius = self.radius
        if (self.keyMap["wheel_zoom_out"] != 0):
            if self.radius <= 38:
                self.radius += 2
                self.setRadius = self.radius
        self.setKey("wheel_zoom_out",0)
        self.setKey("wheel_zoom_in", 0)

        ## Reposition Camera
        x = self.cameratarget.getX() + self.radius * math.sin(math.degrees(self.ZAngle)) * math.cos(math.degrees(self.XYAngle))
        y = self.cameratarget.getY() + self.radius * math.sin(math.degrees(self.ZAngle)) * math.sin(math.degrees(self.XYAngle))
        z = self.cameratarget.getZ() + self.radius * math.cos(math.degrees(self.ZAngle))
        base.camera.setPos(x,y,z)
        base.camera.lookAt(self.cameratarget)
        self.cameratarget.setPos(self.playerBox.getX(),self.playerBox.getY(),self.playerBox.getZ()+6)


        ## Keyboard Movement Controls
        if (self.keyMap["turn_left"]!=0):
            self.playerBox.setH(self.playerBox.getH() + 200 * globalClock.getDt())
        if (self.keyMap["turn_right"]!=0):
            self.playerBox.setH(self.playerBox.getH() - 200 * globalClock.getDt())
        if (self.keyMap["strafe_left"]!=0):
            self.playerBox.setX(self.playerBox, +20 * globalClock.getDt())
        if (self.keyMap["strafe_right"]!=0):
            self.playerBox.setX(self.playerBox, -20 * globalClock.getDt())
        if (self.keyMap["forward"]!=0):
            self.playerBox.setY(self.playerBox, -25 * globalClock.getDt())
        if (self.keyMap["backward"] != 0):
            self.playerBox.setY(self.playerBox, +15 * globalClock.getDt())

        if (self.keyMap["forward"]!=0):
            if self.isMoving == False:
                self.player.setPlayRate(2.5,'run')
                self.player.loop('run')
                self.isMoving = True
        else:
            if self.isMoving:
                self.player.setPlayRate(1,'idle')
                self.player.loop('idle')
                self.isMoving = False

        ## Check Collisions
            

        return task.cont
class Tower(GameObject):
    def __init__(self,player,name,x,y,income):
        global tower_count
        self.my_id = tower_count
        tower_count += 1
        self.player = player
        self.name = name
        self.x = x
        self.y = y
        self.state = "normal"
        self.build_progress = 0.0
        self.build_speed = 1.0
        self.gold_inc = 1.0
        if base.player == self.player:
            base.ecn_manager.gold_inc += self.gold_inc
            base.vis_manager.update()

        self.model_list = ["models/farmhouse_grey.egg","models/farmhouse_red.egg","models/farmhouse_green.egg"]
        self.model_list = ["models/tower_grey.egg","models/tower_red.egg","models/tower_green.egg"]
        self.model = loader.loadModel(self.model_list[self.player])

#        if self.player == 0:
#            self.model = loader.loadModel("models/tower_grey.egg")
#        elif self.player == 1:
#            self.model = loader.loadModel("models/tower_red.egg")
#        elif self.player == 2:
#            self.model = loader.loadModel("models/tower_green.egg")

        self.node_path = NodePath("tower"+str(self.my_id)+"_node_path")
        self.model.reparentTo(self.node_path)
        self.node_path.setPos(x,y,0)
        self.node_path.setTag("player",str(player))
        self.node_path.setScale(tower_scale,tower_scale,tower_scale)
        self.node_path.setColor(1,1,1,0.1)

        self.node_col = self.node_path.attachNewNode(CollisionNode("tower"+str(self.my_id)+"_c_node"))
        self.node_col.setScale((2,2,1))
        self.node_col.setPos(0,0,0)
        self.node_col.node().addSolid(CollisionSphere(0,0,0,1))
        self.node_col.setTag("type","tower")
        base.cTrav.addCollider(self.node_col,base.col_manager.col_handler)
        #self.node_col.show()
        self.node_path.setTag("id",str(self.my_id))
        self.tower_fight_col = self.node_path.attachNewNode(CollisionNode("tower"+str(self.my_id)+"_batcol_node"))
        self.tower_fight_col.setScale((2,2,0.5))
        self.tower_fight_col.setPos(0,0,0)
        self.tower_fight_col.node().addSolid(CollisionSphere(0,0,0,1))
        self.tower_fight_col.setColor(1,0,0,0.1)
        self.tower_fight_col.setTag("player",str(player))
        self.tower_fight_col.setTag("state","normal")
        #self.tower_fight_col.show()
        base.cTrav.addCollider(self.tower_fight_col,base.col_manager.col_handler)

        self.selection_ring = self.selection_ring_create(size = 1.5)
        self.selection_ring.reparentTo(self.node_path)
        self.selection_ring.hide()

        self.node_path.reparentTo(render)

    def capture_check(self):
        has_guard = False
        for a in base.armies:
            if a.player == self.player and (a.state == "normal" or a.state == "battle"):
                if base.calculator.dist_to_point(self.get_x(),self.get_y(),a.get_x(),a.get_y()) < 80:
                    has_guard = True
        if has_guard == True:
            return False
        else:
            return True

    def change_owner(self,new_owner):
        if self.player == base.player:
            base.ecn_manager.gold_inc -= self.gold_inc
        elif new_owner == base.player:
            base.ecn_manager.gold_inc += self.gold_inc
        base.vis_manager.update()
        self.model.remove()
        self.model = loader.loadModel(self.model_list[new_owner])
        self.node_path.setTag("player",str(new_owner))
        self.tower_fight_col.setTag("player",str(new_owner))
        self.player = new_owner
        self.model.reparentTo(self.node_path)

    def build_cancel(self):
        if self.player == base.player:
            base.ecn_manager.gold += base.ecn_manager.cost_army_gold
            base.vis_manager.update()
        if base.single_player == False and base.client == False:
                base.net_manager.server_messager("build_cancel",[self.my_id])
        taskMgr.remove("task_tower"+str(self.my_id)+"_build")
        self.build_progress = 0.0
        if base.vis_manager.statbar.focus == self:
            base.vis_manager.statbar.show_tower(self.my_id)

    def build_start(self):
        if self.player == base.player:
            base.ecn_manager.gold -= base.ecn_manager.cost_army_gold
            base.vis_manager.update()
        print "Started Building"
        if base.single_player == False and base.client == False:
                base.net_manager.server_messager("build_start",[self.my_id,self.player,"army"])
        self.build_progress = self.build_speed
        taskMgr.add(self.task_build,"task_tower"+str(self.my_id)+"_build")
        if base.vis_manager.statbar.focus == self:
            base.vis_manager.statbar.show_tower(self.my_id)

    def build_start_request(self):
        base.net_manager.client_messager("build_start_request",[self.my_id,self.player,"army"])

    def build_cancel_request(self):
        base.net_manager.client_messager("build_cancel_request",[self.my_id])

    def task_build(self,task):
        if self.build_progress < 100.00:
            self.build_progress += self.build_speed
            if base.vis_manager.statbar.focus == self:
                base.vis_manager.statbar.bar_build.set_value(self.build_progress)
            return Task.again
        else:
            self.build_progress = 0.0
            if base.vis_manager.statbar.focus == self:
                base.vis_manager.statbar.show_tower(self.my_id)
            if base.single_player == False and base.client == False:
                base.net_manager.server_messager("build_complete",[self.my_id,self.player,"army"])
            if base.client == False:
                self.create_counter()
            return Task.done

    def create_counter(self):
        new_army = Army(self.player,"Infantry",self.node_path.getX(),self.node_path.getY(),1)
        base.armies.append(new_army)
        new_army.state = "new"
        new_army.army_fight_col.setTag("state","new")
        intvl_exit = new_army.node_path.posInterval(2, Point3(self.x, self.y-24, 0),startPos=Point3(self.x, self.y, 0))

        def army_ready():
            new_army.state = "normal"
            new_army.army_fight_col.setTag("state","normal")

        func_armyready = Func(army_ready)
        sq_army_move = Sequence(intvl_exit,func_armyready)
        sq_army_move.start()
class Battle(GameObject):
    def __init__(self,counters,start=-1):
        global battle_count

        self.combatants = counters
        self.my_id = battle_count
        self.turn = 0
        self.chance_range = 100
        self.chance_success = 80

        self.col_scale_orig = 2.0
        self.col_scale = self.col_scale_orig
        self.col_scale_inc = 0.4

        battle_count += 1

        if start != -1:
            self.turn = start
            self.combatants[start].turn_start()

        coords = [(self.combatants[0].get_x(),self.combatants[0].get_y()),(self.combatants[1].get_x(),self.combatants[1].get_y())]
        self.x,self.y = TCalc.midpoint(coords)

        self.node_path = NodePath("battle"+str(self.my_id)+"_node_path")
        self.node_path.setPos(self.x,self.y,0)
        self.node_path.setTag("id",str(self.my_id))
        self.node_path.setTag("type","battle")
        self.node_path.reparentTo(render)

        self.bat_col = self.node_path.attachNewNode(CollisionNode("battle"+str(self.my_id)+"_c_node"))
        self.bat_col.setScale((self.col_scale,self.col_scale,0.2))
        self.bat_col.setPos(0,0,0)
        self.bat_col.node().addSolid(CollisionSphere(0,0,0,10))
        self.bat_col.setTag("type","battle")
        self.bat_col.show()

        self.battle_speed = 1.0

        for a in self.combatants:
            #a.turn_start()
            a.stop()
            a.state = "battle"
            a.army_fight_col.setTag("state","battle")
            a.battle = self.my_id

        if base.client == False:
            taskMgr.add(self.battle_init_rolls, "battle"+str(self.my_id)+"_task_start")

    def recenter(self):
        new_x = 0.0
        new_y = 0.0
        x_list = []
        y_list = []
        counter = 0
        try:
            for a in self.combatants:
                if a.state != "dead":
                    x_list.append(a.node_path.getX())
                    y_list.append(a.node_path.getY())
                    counter += 1
                    new_x += a.node_path.getX()
                    new_y += a.node_path.getY()
            new_x /= len(x_list)
            new_y /= len(y_list)

            self.node_path.setPos(new_x,new_y,0)
        except:
            pass

    def shrink(self):
        if len(self.combatants) <= 10:
            self.col_scale -= self.col_scale_orig*self.col_scale_inc
            self.bat_col.setScale((self.col_scale,self.col_scale,0.2))

    def battle_init_rolls(self,task):
        init_rolls = []
        highest_roll = -1
        counter = 0
        leader = 0
        for a in self.combatants:
            roll = random.randint(0,self.chance_range)+a.stat_init
            print counter,"rolled",roll
            init_rolls.append(roll)
            if roll > highest_roll:
                highest_roll = roll
                leader = counter
            counter += 1
        self.turn = leader
        print leader,"wins!"
        self.combatants[self.turn].turn_start()

        a1 = self.combatants[0]
        a2 = self.combatants[1]

        if base.client == False:
            if base.single_player == False:
                base.net_manager.server_messager("battle_start",[a1.my_id,a1.node_path.getX(),a1.node_path.getY(),
                                                                 a2.my_id,a2.node_path.getX(),a2.node_path.getY(),
                                                                 self.turn])
            taskMgr.doMethodLater(1,self.battle_loop,"battle"+str(self.my_id)+"_task_loop")
        self.get_odds()
        return task.done

    def get_odds(self):
        side1 = []
        side2 = []
        counter = 0
        for a in self.combatants:
            if a.player == 1 and a.state != "dead":
                side1.append(a)
                counter += 1
            elif a.player == 2 and a.state != "dead":
                side2.append(a)
                counter += 1
        self.odds = (100/counter)*len(side1)
        if base.col_manager.selected_node == self.node_path:
            base.vis_manager.statbar.refresh_battle(self.odds)

    def target_recheck(self):
        army = self.combatants[self.turn]
        target_id = random.randint(0,len(self.combatants)-1)
        target = self.combatants[target_id]
        while target == army or target.player == army.player or target.state == "dead":
            target_id = random.randint(0,len(self.combatants)-1)
            target = self.combatants[target_id]
            print "recheck target - aquired",target_id
        return army,target,target_id

    def turn_change(self,new_turn):
        self.combatants[self.turn].turn_end()
        self.combatants[new_turn].turn_start()
        self.turn = new_turn

    def battle_loop(self,task):
        towerBuff = 0
        battle_end = False
        army,target,target_id = self.target_recheck()

        task.delayTime = self.battle_speed+army.stat_delay
        roll = random.randint(0,self.chance_range)+army.stat_hit

        #Make towers pown arse
        for t in base.towers:
            if t.player == army.player:
                distanceToTower = base.calculator.dist_to_point(army.get_x(),army.get_y(),t.get_x(),t.get_y())
                if  distanceToTower < 80:
                    towerBuff = random.randint(0, 40)
                    roll+=towerBuff

        if roll >= self.chance_success:
            roll = random.randint(0,self.chance_range)+target.stat_block
            if roll >= self.chance_success:
                result = "block"
            else:
                result = "hit"
                target.state = "dead"
                battle_end = True
                for a in self.combatants:
                    if a.player != army.player and a.state != "dead":
                        battle_end = False
        else:
            result = "fail"

        if base.client == False and base.single_player == False:
            randomness = 80
            army.battle_shuffle(self.node_path.getX()+random.randint(0,randomness)-randomness/2,self.node_path.getY()+random.randint(0,randomness)-randomness/2)

        if base.single_player == False:
            base.net_manager.server_messager("battle_clash",[self.my_id,army.my_id,target.my_id,result,towerBuff])
        self.clash(army,target,result,towerBuff)

        army.turn_end()
        last_turn = self.turn

        if battle_end:
            if base.single_player == False:
                base.net_manager.server_messager("battle_end",[self.my_id])
            self.end()
            return task.done
        else:
            self.get_odds()
            if self.turn < len(self.combatants)-1:
                self.turn += 1
            else:
                self.turn = 0
            while self.combatants[self.turn].state == "dead":
                if self.turn < len(self.combatants)-1:
                    self.turn += 1
                else:
                    self.turn = 0
            if base.single_player == False:
                base.net_manager.server_messager("battle_turn",[self.my_id,self.turn])
            self.combatants[self.turn].turn_start()
            return task.again

    def end(self):
        if base.col_manager.selected_node == self.node_path:
                base.vis_manager.statbar.reset_statbar()
        for a in self.combatants:
            a.turn_end()
            if a.state != "dead":
                a.state = "normal"
                a.battle = -1
                a.army_fight_col.setTag("state","normal")
        self.destroy()

    def clash(self,a1,a2,result,buff):
        if buff != 0:
            buffText = "^+" +str(buff)
            TimVisuals.BattleText(self.node_path,buffText,self.x,self.y + 10,(1,1,0,1))
        if result == "block":
            TimVisuals.BattleText(self.node_path,"BLOCK!",self.x,self.y,a2.colour)
        elif result == "hit":
            TimVisuals.BattleText(self.node_path,"HIT AND KILL!",self.x,self.y,a1.colour)
            a2.state = "dead"
            a2.die()
        else:
            TimVisuals.BattleText(self.node_path,"Attack Failed!",self.x,self.y,a1.colour)

    def add_army(self,army):
        army.stop()
        army.state = "battle"
        army.army_fight_col.setTag("state","battle")
        army.battle = self.my_id
        self.combatants.append(army)
        if len(self.combatants) <= 10:
            self.col_scale += self.col_scale_orig*self.col_scale_inc
            self.bat_col.setScale((self.col_scale,self.col_scale,0.2))

        self.get_odds()
        self.recenter()

    def destroy(self):
        self.node_path.removeNode()
Exemple #17
0
class Tower(GameObject):
    def __init__(self, player, name, x, y, income):
        global tower_count
        self.my_id = tower_count
        tower_count += 1
        self.player = player
        self.name = name
        self.x = x
        self.y = y
        self.state = "normal"
        self.build_progress = 0.0
        self.build_speed = 1.0
        self.gold_inc = 1.0
        if base.player == self.player:
            base.ecn_manager.gold_inc += self.gold_inc
            base.vis_manager.update()

        self.model_list = [
            "models/farmhouse_grey.egg", "models/farmhouse_red.egg",
            "models/farmhouse_green.egg"
        ]
        self.model_list = [
            "models/tower_grey.egg", "models/tower_red.egg",
            "models/tower_green.egg"
        ]
        self.model = loader.loadModel(self.model_list[self.player])

        #        if self.player == 0:
        #            self.model = loader.loadModel("models/tower_grey.egg")
        #        elif self.player == 1:
        #            self.model = loader.loadModel("models/tower_red.egg")
        #        elif self.player == 2:
        #            self.model = loader.loadModel("models/tower_green.egg")

        self.node_path = NodePath("tower" + str(self.my_id) + "_node_path")
        self.model.reparentTo(self.node_path)
        self.node_path.setPos(x, y, 0)
        self.node_path.setTag("player", str(player))
        self.node_path.setScale(tower_scale, tower_scale, tower_scale)
        self.node_path.setColor(1, 1, 1, 0.1)

        self.node_col = self.node_path.attachNewNode(
            CollisionNode("tower" + str(self.my_id) + "_c_node"))
        self.node_col.setScale((2, 2, 1))
        self.node_col.setPos(0, 0, 0)
        self.node_col.node().addSolid(CollisionSphere(0, 0, 0, 1))
        self.node_col.setTag("type", "tower")
        base.cTrav.addCollider(self.node_col, base.col_manager.col_handler)
        #self.node_col.show()
        self.node_path.setTag("id", str(self.my_id))
        self.tower_fight_col = self.node_path.attachNewNode(
            CollisionNode("tower" + str(self.my_id) + "_batcol_node"))
        self.tower_fight_col.setScale((2, 2, 0.5))
        self.tower_fight_col.setPos(0, 0, 0)
        self.tower_fight_col.node().addSolid(CollisionSphere(0, 0, 0, 1))
        self.tower_fight_col.setColor(1, 0, 0, 0.1)
        self.tower_fight_col.setTag("player", str(player))
        self.tower_fight_col.setTag("state", "normal")
        #self.tower_fight_col.show()
        base.cTrav.addCollider(self.tower_fight_col,
                               base.col_manager.col_handler)

        self.selection_ring = self.selection_ring_create(size=1.5)
        self.selection_ring.reparentTo(self.node_path)
        self.selection_ring.hide()

        self.node_path.reparentTo(render)

    def capture_check(self):
        has_guard = False
        for a in base.armies:
            if a.player == self.player and (a.state == "normal"
                                            or a.state == "battle"):
                if base.calculator.dist_to_point(self.get_x(), self.get_y(),
                                                 a.get_x(), a.get_y()) < 80:
                    has_guard = True
        if has_guard == True:
            return False
        else:
            return True

    def change_owner(self, new_owner):
        if self.player == base.player:
            base.ecn_manager.gold_inc -= self.gold_inc
        elif new_owner == base.player:
            base.ecn_manager.gold_inc += self.gold_inc
        base.vis_manager.update()
        self.model.remove()
        self.model = loader.loadModel(self.model_list[new_owner])
        self.node_path.setTag("player", str(new_owner))
        self.tower_fight_col.setTag("player", str(new_owner))
        self.player = new_owner
        self.model.reparentTo(self.node_path)

    def build_cancel(self):
        if self.player == base.player:
            base.ecn_manager.gold += base.ecn_manager.cost_army_gold
            base.vis_manager.update()
        if base.single_player == False and base.client == False:
            base.net_manager.server_messager("build_cancel", [self.my_id])
        taskMgr.remove("task_tower" + str(self.my_id) + "_build")
        self.build_progress = 0.0
        if base.vis_manager.statbar.focus == self:
            base.vis_manager.statbar.show_tower(self.my_id)

    def build_start(self):
        if self.player == base.player:
            base.ecn_manager.gold -= base.ecn_manager.cost_army_gold
            base.vis_manager.update()
        print "Started Building"
        if base.single_player == False and base.client == False:
            base.net_manager.server_messager("build_start",
                                             [self.my_id, self.player, "army"])
        self.build_progress = self.build_speed
        taskMgr.add(self.task_build, "task_tower" + str(self.my_id) + "_build")
        if base.vis_manager.statbar.focus == self:
            base.vis_manager.statbar.show_tower(self.my_id)

    def build_start_request(self):
        base.net_manager.client_messager("build_start_request",
                                         [self.my_id, self.player, "army"])

    def build_cancel_request(self):
        base.net_manager.client_messager("build_cancel_request", [self.my_id])

    def task_build(self, task):
        if self.build_progress < 100.00:
            self.build_progress += self.build_speed
            if base.vis_manager.statbar.focus == self:
                base.vis_manager.statbar.bar_build.set_value(
                    self.build_progress)
            return Task.again
        else:
            self.build_progress = 0.0
            if base.vis_manager.statbar.focus == self:
                base.vis_manager.statbar.show_tower(self.my_id)
            if base.single_player == False and base.client == False:
                base.net_manager.server_messager(
                    "build_complete", [self.my_id, self.player, "army"])
            if base.client == False:
                self.create_counter()
            return Task.done

    def create_counter(self):
        new_army = Army(self.player, "Infantry", self.node_path.getX(),
                        self.node_path.getY(), 1)
        base.armies.append(new_army)
        new_army.state = "new"
        new_army.army_fight_col.setTag("state", "new")
        intvl_exit = new_army.node_path.posInterval(
            2,
            Point3(self.x, self.y - 24, 0),
            startPos=Point3(self.x, self.y, 0))

        def army_ready():
            new_army.state = "normal"
            new_army.army_fight_col.setTag("state", "normal")

        func_armyready = Func(army_ready)
        sq_army_move = Sequence(intvl_exit, func_armyready)
        sq_army_move.start()
Exemple #18
0
class Vehicle(ActorNode):
    def __init__(self, parent=None):
        '''
        Create a new Vehicle node. Physics should be initialized before any
        instances of Vehicle are created.

        arguments:
          parent -- A PandaNode for the vehicle to attach to. Default is None,
                    in which case the Vehicle should be added to the scene
                    graph via NodePath.attachNewNode().

        '''
        ActorNode.__init__(self, 'VehiclePhysics')
        base.physicsMgr.attachPhysicalNode(self)

        self.getPhysicsObject().setMass(MASS)
        if parent:
            self.myPath = parent.attachNewNode(self)
        else:
            self.myPath = NodePath(self)

        # Load vehicle model and place in the transparent bin.
        vehicleModel = loader.loadModel(MODEL_PATH)
        hull = vehicleModel.find('**/Hull')
        hull.setBin('transparent', 30)
        pwnsEnclosure = vehicleModel.find('**/Pwns_Enclosure')
        pwnsEnclosure.setBin('transparent', 30)
        self.myPath.setPos(0, 0, -0.0)
        selectable = self.myPath.attachNewNode(SelectableNode('vehicle sel'))
        vehicleModel.reparentTo(selectable)

        # ==== Initialize Physics ==== #
        thrusterForceNode = ForceNode('ThrusterForce')
        self.myPath.attachNewNode(thrusterForceNode)

        self.linearForce = LinearVectorForce(0, 0, 0)
        self.linearForce.setMassDependent(1)
        self.angularForce = AngularVectorForce(0, 0, 0)

        thrusterForceNode.addForce(self.linearForce)
        thrusterForceNode.addForce(self.angularForce)

        self.getPhysical(0).addLinearForce(self.linearForce)
        self.getPhysical(0).addAngularForce(self.angularForce)

        self.previousXY = (self.myPath.getX(), self.myPath.getY())

        self.tm = ThrusterManager()

        # Add self.updatePhysics to the task manager and run this task as
        # frequently as possible.
        self.updatePhysicsTask = taskMgr.add(self.updatePhysics,
                                             'UpdatePhysics')

        # ==== Initialize Cameras ==== #
        lens = PerspectiveLens()
        lens.setNearFar(0.05, 100.0)
        #Use either FocalLength or Fov. Fov ~40 is about what actual forward cameras are
        #lens.setFocalLength(0.8)
        lens.setFov(70, 70)
        camera = Camera("Forward_left", lens).getPath()
        camera.reparentTo(vehicleModel.find('**/Forward_Camera'))
        camera.setX(camera.getX() - 0.1)  # Forward cameras 20cm apart
        camera.setY(
            camera.getY() +
            0.05)  # Move in front of torpedo tubes to avoid abstruction
        camera.setHpr(0, 0, 0)

        camera = Camera("Forward_right", lens).getPath()
        camera.reparentTo(vehicleModel.find('**/Forward_Camera'))
        camera.setX(camera.getX() + 0.1)  # Forward cameras 20cm apart
        camera.setY(
            camera.getY() +
            0.05)  # Move in front of torpedo tubes to avoid abstruction
        camera.setHpr(0, 0, 0)

        lens = PerspectiveLens()
        lens.setNearFar(0.05, 100.0)
        lens.setFocalLength(0.8)
        camera = Camera("Downward", lens).getPath()
        camera.reparentTo(vehicleModel.find('**/Downward_Camera'))
        camera.setHpr(0, -90, 0)

        #Layout link (to access hydrophone information)
        self.layout = None

        #Hydrophone variables
        self.start_time = time()
        self.last_hydro_update = time()

    def setLayout(self, layout):
        #Add a link to the layout to allow for referencing other objects
        #This is necessary for the hydrophone addition
        self.layout = layout

    def getDepth(self):
        ''' Returns the depth of the vehicle, in meters. '''
        return -0.15 - self.myPath.getZ()

    def getHeading(self):
        ''' Returns the heading of the vehicle, in clockwise degrees. '''
        # Panda uses counter-clockwise degrees, with the range (-180, 180].
        heading = self.myPath.getH()
        if heading < 0:
            return -heading
        elif heading > 0:
            return 360 - heading
        else:
            return 0

    def updatePhysics(self, task):
        '''
        Use the motor PWM values calculated by the controller to apply forces
        to the simulated vehicle.

        This runs at every frame, so it needs to complete quickly.

        '''
        outputs = shm.kalman.get()
        self.tm.update(outputs)
        passive_wrench = vehicle.passive_forces(outputs, self.tm)
        passive_forces, passive_torques = passive_wrench[:3], \
                                          passive_wrench[3:]

        # Get motor thrusts
        thrusts = np.array(self.tm.get_thrusts())

        # Add passive forces and torques to that produced by thrusters,
        # converting them to sub space first.
        force = self.tm.total_thrust(thrusts) + \
                self.tm.orientation.conjugate() * passive_forces
        torque = self.tm.total_torque(thrusts) + \
                self.tm.orientation.conjugate() * passive_torques

        # Finally apply forces and torques to the model
        # we also need to account for panda3d's strange coordinate system
        # (x and y are flipped and z points up (instead of down))
        self.linearForce.setVector(force_subspace[1], \
                                   force_subspace[0], \
                                  -force_subspace[2])

        # We're supposed to use axis angle here, but I'm being sneaky
        # and using the torque vector directly, i.e. non normalized axis angle
        # with the hopes that this LRotationf constructor will figure it out
        self.angularForce.setQuat(\
            LRotationf(LVector3f(torque_subspace[1], \
                                 torque_subspace[0], \
                                -torque_subspace[2]), 1))

        # Update shared variables for controller
        outputs.heading = self.getHeading()
        outputs.pitch = self.myPath.getP()
        outputs.roll = self.myPath.getR()

        # This velocity is in world space
        # We need to put it into THRUST CONVENTION SPACE
        # which we assume kalman outputs in...
        velocity = self.getPhysicsObject().getVelocity()

        # Bring the velocity into THRUST CONVENTION SPACE
        # Don't forget to account for panda's coordinate system
        velocity = self.tm.heading_quat.conjugate() * \
                  np.array((velocity.getY(), velocity.getX(), -velocity.getZ()))

        outputs.velx = velocity[0]
        outputs.vely = velocity[1]
        outputs.depth_rate = velocity[2]

        outputs.depth = self.getDepth()
        outputs.north = self.myPath.getY()
        outputs.east = self.myPath.getX()

        dX = self.myPath.getX() - self.previousXY[0]
        dY = self.myPath.getY() - self.previousXY[1]

        # Forward and sway are in THRUST CONVENTION SPACE
        # don't forget to account for panda's coordinate system
        dF, dS, dD = self.tm.heading_quat.conjugate() * np.array((dY, dX, 0.0))

        outputs.forward += dF
        outputs.sway += dS

        # Output some quaternions, accounting for Panda's coordinate system
        outputs.q0, outputs.q2, outputs.q1, outputs.q3 = self.myPath.getQuat()
        outputs.q3 *= -1.0

        shm.kalman.set(outputs)

        svHeadingInt.set(self.getHeading())
        svDepth.set(self.getDepth())
        #XXX: Approximate altitude assuming that the pool is 12 feet deep
        svAltitude.set(3.6 - self.getDepth())
        svDvlDmgNorth.set(self.myPath.getY())
        svDvlDmgEast.set(self.myPath.getX())

        self.previousXY = (self.myPath.getX(), self.myPath.getY())  #update

        self.output_hydro_data()

        return Task.cont

    def output_hydro_data(self):
        #Update simulated hydrophone values
        pingers = []  #Get all pingers from the layout
        for element in self.layout.elements:
            if element.getTypeName() == "Pinger":
                pingers.append(element)

        HYDRO_TICK_PERIOD = 1

        if time() - self.last_hydro_update > HYDRO_TICK_PERIOD:
            dt = time() - self.last_hydro_update
            self.last_hydro_update = time()

            if shm.hydrophones_settings.dsp_mode.get() == 1:  #Search mode
                #Incr search count
                shm.hydrophones_results.search_count.set(
                    shm.hydrophones_results.search_count.get() + 1)

                #Generate proper "hydrophone bins" marks
                sb = 0
                for p in pingers:
                    f = p.pinger_frequency
                    dc = (f - (shm.hydrophones_settings.searchCenter.get() -
                               shm.hydrophones_settings.searchDelta.get())
                          ) / shm.hydrophones_settings.searchStep.get() + 0.5
                    sb |= 1 << int(dc)
                shm.hydrophones_results.search_bins.set(sb)

            else:  #Track Mode
                #Incr ping count
                shm.hydrophones_results.ping_count.set(
                    shm.hydrophones_results.ping_count.get() + 1)

                #Determine which pinger we are actively tracking (within 0.7khz of target)
                targetp = None
                for p in pingers:
                    if abs(shm.hydrophones_settings.trackFrequency.get() -
                           p.pinger_frequency) < 700:
                        targetp = p

                if targetp is not None:
                    shm.hydrophones_results.intensity.set(
                        int(shm.hydrophones_settings.trackMagThresh.get() +
                            1e4 * random()))
                    shm.hydrophones_results.ping_time.set(int(dt * 1000))

                    pp = targetp.path.getPos()

                    vv = vector.Vector(self.myPath.getY(), self.myPath.getX())
                    pv = vector.Vector(pp.getY(), pp.getX())

                    #heading
                    dv = pv - vv
                    ang = vector.GetAuvAngle(dv)
                    hdiff = helpers.heading_diff(self.getHeading(), ang)

                    shm.hydrophones_results.heading.set(hdiff)

                    #elevation
                    dh = self.myPath.getZ() - pp.getZ()
                    dist = vector.Length(dv)
                    elev = math.degrees(math.atan2(dist, dh))
                    elev = min(elev, 90)

                    shm.hydrophones_results.elevation.set(elev)

                    #phase calculations
                    dy = self.myPath.getY() - pp.getY()
                    dx = self.myPath.getX() - pp.getX()
                    yang = math.degrees(math.atan2(dist, dy))
                    xang = math.degrees(math.atan2(dist, dx))

                    shm.hydrophones_results.phaseX.set((90.0 - xang) / 90.0)
                    shm.hydrophones_results.phaseY.set((90.0 - yang) / 90.0)
                    shm.hydrophones_results.phaseZ.set((90.0 - elev) / 90.0)

                else:
                    shm.hydrophones_results.heading.set(0)
                    shm.hydrophones_results.elevation.set(0)
                    shm.hydrophones_results.intensity.set(0)
                    shm.hydrophones_results.ping_time.set(0)

            shm.hydrophones_results.uptime.set(int(time() - self.start_time))

    def __del__(self):
        ''' Remove update tasks from the panda task manager. '''
        taskMgr.remove(self.updatePhysicsTask)
        ActorNode.__del__(self)
Exemple #19
0
class Battle(GameObject):
    def __init__(self, counters, start=-1):
        global battle_count

        self.combatants = counters
        self.my_id = battle_count
        self.turn = 0
        self.chance_range = 100
        self.chance_success = 80

        self.col_scale_orig = 2.0
        self.col_scale = self.col_scale_orig
        self.col_scale_inc = 0.4

        battle_count += 1

        if start != -1:
            self.turn = start
            self.combatants[start].turn_start()

        coords = [(self.combatants[0].get_x(), self.combatants[0].get_y()),
                  (self.combatants[1].get_x(), self.combatants[1].get_y())]
        self.x, self.y = TCalc.midpoint(coords)

        self.node_path = NodePath("battle" + str(self.my_id) + "_node_path")
        self.node_path.setPos(self.x, self.y, 0)
        self.node_path.setTag("id", str(self.my_id))
        self.node_path.setTag("type", "battle")
        self.node_path.reparentTo(render)

        self.bat_col = self.node_path.attachNewNode(
            CollisionNode("battle" + str(self.my_id) + "_c_node"))
        self.bat_col.setScale((self.col_scale, self.col_scale, 0.2))
        self.bat_col.setPos(0, 0, 0)
        self.bat_col.node().addSolid(CollisionSphere(0, 0, 0, 10))
        self.bat_col.setTag("type", "battle")
        self.bat_col.show()

        self.battle_speed = 1.0

        for a in self.combatants:
            #a.turn_start()
            a.stop()
            a.state = "battle"
            a.army_fight_col.setTag("state", "battle")
            a.battle = self.my_id

        if base.client == False:
            taskMgr.add(self.battle_init_rolls,
                        "battle" + str(self.my_id) + "_task_start")

    def recenter(self):
        new_x = 0.0
        new_y = 0.0
        x_list = []
        y_list = []
        counter = 0
        try:
            for a in self.combatants:
                if a.state != "dead":
                    x_list.append(a.node_path.getX())
                    y_list.append(a.node_path.getY())
                    counter += 1
                    new_x += a.node_path.getX()
                    new_y += a.node_path.getY()
            new_x /= len(x_list)
            new_y /= len(y_list)

            self.node_path.setPos(new_x, new_y, 0)
        except:
            pass

    def shrink(self):
        if len(self.combatants) <= 10:
            self.col_scale -= self.col_scale_orig * self.col_scale_inc
            self.bat_col.setScale((self.col_scale, self.col_scale, 0.2))

    def battle_init_rolls(self, task):
        init_rolls = []
        highest_roll = -1
        counter = 0
        leader = 0
        for a in self.combatants:
            roll = random.randint(0, self.chance_range) + a.stat_init
            print counter, "rolled", roll
            init_rolls.append(roll)
            if roll > highest_roll:
                highest_roll = roll
                leader = counter
            counter += 1
        self.turn = leader
        print leader, "wins!"
        self.combatants[self.turn].turn_start()

        a1 = self.combatants[0]
        a2 = self.combatants[1]

        if base.client == False:
            if base.single_player == False:
                base.net_manager.server_messager("battle_start", [
                    a1.my_id,
                    a1.node_path.getX(),
                    a1.node_path.getY(), a2.my_id,
                    a2.node_path.getX(),
                    a2.node_path.getY(), self.turn
                ])
            taskMgr.doMethodLater(1, self.battle_loop,
                                  "battle" + str(self.my_id) + "_task_loop")
        self.get_odds()
        return task.done

    def get_odds(self):
        side1 = []
        side2 = []
        counter = 0
        for a in self.combatants:
            if a.player == 1 and a.state != "dead":
                side1.append(a)
                counter += 1
            elif a.player == 2 and a.state != "dead":
                side2.append(a)
                counter += 1
        self.odds = (100 / counter) * len(side1)
        if base.col_manager.selected_node == self.node_path:
            base.vis_manager.statbar.refresh_battle(self.odds)

    def target_recheck(self):
        army = self.combatants[self.turn]
        target_id = random.randint(0, len(self.combatants) - 1)
        target = self.combatants[target_id]
        while target == army or target.player == army.player or target.state == "dead":
            target_id = random.randint(0, len(self.combatants) - 1)
            target = self.combatants[target_id]
            print "recheck target - aquired", target_id
        return army, target, target_id

    def turn_change(self, new_turn):
        self.combatants[self.turn].turn_end()
        self.combatants[new_turn].turn_start()
        self.turn = new_turn

    def battle_loop(self, task):
        towerBuff = 0
        battle_end = False
        army, target, target_id = self.target_recheck()

        task.delayTime = self.battle_speed + army.stat_delay
        roll = random.randint(0, self.chance_range) + army.stat_hit

        #Make towers pown arse
        for t in base.towers:
            if t.player == army.player:
                distanceToTower = base.calculator.dist_to_point(
                    army.get_x(), army.get_y(), t.get_x(), t.get_y())
                if distanceToTower < 80:
                    towerBuff = random.randint(0, 40)
                    roll += towerBuff

        if roll >= self.chance_success:
            roll = random.randint(0, self.chance_range) + target.stat_block
            if roll >= self.chance_success:
                result = "block"
            else:
                result = "hit"
                target.state = "dead"
                battle_end = True
                for a in self.combatants:
                    if a.player != army.player and a.state != "dead":
                        battle_end = False
        else:
            result = "fail"

        if base.client == False and base.single_player == False:
            randomness = 80
            army.battle_shuffle(
                self.node_path.getX() + random.randint(0, randomness) -
                randomness / 2,
                self.node_path.getY() + random.randint(0, randomness) -
                randomness / 2)

        if base.single_player == False:
            base.net_manager.server_messager(
                "battle_clash",
                [self.my_id, army.my_id, target.my_id, result, towerBuff])
        self.clash(army, target, result, towerBuff)

        army.turn_end()
        last_turn = self.turn

        if battle_end:
            if base.single_player == False:
                base.net_manager.server_messager("battle_end", [self.my_id])
            self.end()
            return task.done
        else:
            self.get_odds()
            if self.turn < len(self.combatants) - 1:
                self.turn += 1
            else:
                self.turn = 0
            while self.combatants[self.turn].state == "dead":
                if self.turn < len(self.combatants) - 1:
                    self.turn += 1
                else:
                    self.turn = 0
            if base.single_player == False:
                base.net_manager.server_messager("battle_turn",
                                                 [self.my_id, self.turn])
            self.combatants[self.turn].turn_start()
            return task.again

    def end(self):
        if base.col_manager.selected_node == self.node_path:
            base.vis_manager.statbar.reset_statbar()
        for a in self.combatants:
            a.turn_end()
            if a.state != "dead":
                a.state = "normal"
                a.battle = -1
                a.army_fight_col.setTag("state", "normal")
        self.destroy()

    def clash(self, a1, a2, result, buff):
        if buff != 0:
            buffText = "^+" + str(buff)
            TimVisuals.BattleText(self.node_path, buffText, self.x,
                                  self.y + 10, (1, 1, 0, 1))
        if result == "block":
            TimVisuals.BattleText(self.node_path, "BLOCK!", self.x, self.y,
                                  a2.colour)
        elif result == "hit":
            TimVisuals.BattleText(self.node_path, "HIT AND KILL!", self.x,
                                  self.y, a1.colour)
            a2.state = "dead"
            a2.die()
        else:
            TimVisuals.BattleText(self.node_path, "Attack Failed!", self.x,
                                  self.y, a1.colour)

    def add_army(self, army):
        army.stop()
        army.state = "battle"
        army.army_fight_col.setTag("state", "battle")
        army.battle = self.my_id
        self.combatants.append(army)
        if len(self.combatants) <= 10:
            self.col_scale += self.col_scale_orig * self.col_scale_inc
            self.bat_col.setScale((self.col_scale, self.col_scale, 0.2))

        self.get_odds()
        self.recenter()

    def destroy(self):
        self.node_path.removeNode()
Exemple #20
0
class PartyCog(FSM):
    notify = directNotify.newCategory('PartyCog')
    HpTextGenerator = TextNode('HpTextGenerator')
    hpText = None
    height = 7

    def __init__(self,
                 parentNode,
                 id,
                 bounceSpeed=3,
                 bounceHeight=1,
                 rotateSpeed=1,
                 heightShift=1,
                 xMoveSpeed=0,
                 xMoveDistance=0,
                 bounceOffset=0):
        self.id = id
        FSM.__init__(self, 'PartyCogFSM-%d' % self.id)
        self.showFacingStatus = False
        self.xMoveSpeed = xMoveSpeed
        self.xMoveDistance = xMoveDistance
        self.heightShift = heightShift
        self.bounceSpeed = bounceSpeed
        self.bounceHeight = bounceHeight
        self.rotateSpeed = rotateSpeed
        self.parentNode = parentNode
        self.bounceOffset = bounceOffset
        self.hitInterval = None
        self.kaboomTrack = None
        self.resetRollIval = None
        self.netTimeSentToStartByHit = 0
        self.load()
        self.request('Down')
        return

    def load(self):
        self.root = NodePath('PartyCog-%d' % self.id)
        self.root.reparentTo(self.parentNode)
        path = 'phase_13/models/parties/cogPinata_'
        self.actor = Actor(
            path + 'actor', {
                'idle': path + 'idle_anim',
                'down': path + 'down_anim',
                'up': path + 'up_anim',
                'bodyHitBack': path + 'bodyHitBack_anim',
                'bodyHitFront': path + 'bodyHitFront_anim',
                'headHitBack': path + 'headHitBack_anim',
                'headHitFront': path + 'headHitFront_anim'
            })
        self.actor.reparentTo(self.root)
        self.temp_transform = Mat4()
        self.head_locator = self.actor.attachNewNode('temphead')
        self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75)
        self.bodyColl.setTangible(1)
        self.bodyCollNode = CollisionNode('PartyCog-%d-Body-Collision' %
                                          self.id)
        self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.bodyCollNode.addSolid(self.bodyColl)
        self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode)
        self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5)
        self.headColl.setTangible(1)
        self.headCollNode = CollisionNode('PartyCog-%d-Head-Collision' %
                                          self.id)
        self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.headCollNode.addSolid(self.headColl)
        self.headCollNodePath = self.root.attachNewNode(self.headCollNode)
        self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0)
        self.arm1Coll.setTangible(1)
        self.arm1CollNode = CollisionNode('PartyCog-%d-Arm1-Collision' %
                                          self.id)
        self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm1CollNode.addSolid(self.arm1Coll)
        self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode)
        self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0)
        self.arm2Coll.setTangible(1)
        self.arm2CollNode = CollisionNode('PartyCog-%d-Arm2-Collision' %
                                          self.id)
        self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm2CollNode.addSolid(self.arm2Coll)
        self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode)
        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splatType = globalPropPool.getPropType(splatName)
        self.pieHitSound = globalBattleSoundCache.getSound(
            'AA_wholepie_only.ogg')
        self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.ogg')
        self.hole = loader.loadModel('phase_13/models/parties/cogPinataHole')
        self.hole.setTransparency(True)
        self.hole.setP(-90.0)
        self.hole.setScale(3)
        self.hole.setBin('ground', 3)
        self.hole.reparentTo(self.parentNode)

    def unload(self):
        self.request('Off')
        self.clearHitInterval()
        if self.hole is not None:
            self.hole.removeNode()
            self.hole = None
        if self.actor is not None:
            self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None
        if self.root is not None:
            self.root.removeNode()
            self.root = None
        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.kaboomTrack = None
        if self.resetRollIval is not None and self.resetRollIval.isPlaying():
            self.resetRollIval.finish()
        self.resetRollIval = None
        if self.hitInterval is not None and self.hitInterval.isPlaying():
            self.hitInterval.finish()
        self.hitInterval = None
        del self.upSound
        del self.pieHitSound
        return

    def enterStatic(self):
        pass

    def exitStatic(self):
        pass

    def enterActive(self, startTime):
        self.root.setR(0.0)
        updateTask = Task.Task(self.updateTask)
        updateTask.startTime = startTime
        taskMgr.add(updateTask, 'PartyCog.update-%d' % self.id)

    def exitActive(self):
        taskMgr.remove('PartyCog.update-%d' % self.id)
        taskMgr.remove('PartyCog.bounceTask-%d' % self.id)
        self.clearHitInterval()
        self.resetRollIval = self.root.hprInterval(0.5,
                                                   Point3(
                                                       self.root.getH(), 0.0,
                                                       0.0),
                                                   blendType='easeInOut')
        self.resetRollIval.start()
        self.actor.stop()

    def enterDown(self):
        if self.oldState == 'Off':
            downAnimControl = self.actor.getAnimControl('down')
            self.actor.pose('down', downAnimControl.getNumFrames() - 1)
            return
        self.clearHitInterval()
        startScale = self.hole.getScale()
        endScale = Point3(5, 5, 5)
        self.hitInterval = Sequence(
            LerpFunc(self.setAlongSpline,
                     duration=1.0,
                     fromData=self.currentT,
                     toData=0.0),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=endScale,
                              startScale=startScale,
                              blendType='easeIn'),
            Parallel(
                SoundInterval(self.upSound,
                              volume=0.6,
                              node=self.actor,
                              cutOff=PartyGlobals.PARTY_COG_CUTOFF),
                ActorInterval(self.actor, 'down', loop=0)),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=Point3(3, 3, 3),
                              startScale=endScale,
                              blendType='easeOut'))
        self.hitInterval.start()

    def exitDown(self):
        self.root.setR(0.0)
        self.root.setH(0.0)
        self.targetDistance = 0.0
        self.targetFacing = 0.0
        self.currentT = 0.0
        self.setAlongSpline(0.0)
        self.clearHitInterval()
        startScale = self.hole.getScale()
        endScale = Point3(5, 5, 5)
        self.hitInterval = Sequence(
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=endScale,
                              startScale=startScale,
                              blendType='easeIn'),
            Parallel(
                SoundInterval(self.upSound,
                              volume=0.6,
                              node=self.actor,
                              cutOff=PartyGlobals.PARTY_COG_CUTOFF),
                ActorInterval(self.actor, 'up', loop=0)),
            Func(self.actor.loop, 'idle'),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=Point3(3, 3, 3),
                              startScale=endScale,
                              blendType='easeOut'))
        self.hitInterval.start()

    def filterDown(self, request, args):
        if request == 'Down':
            return None
        else:
            return self.defaultFilter(request, args)
        return None

    def setEndPoints(self, start, end, amplitude=1.7):
        self.sinAmplitude = amplitude
        self.sinPeriod = (end.getX() - start.getX()) / 2
        self.sinDisplacement = start.getY()
        self.startPoint = start
        self.endPoint = end
        self.currentT = 0.0
        self.targetDistance = 0.0
        self.currentFacing = 0.0
        self.targetFacing = 0.0
        self.setAlongSpline(self.currentT)
        self.hole.setPos(self.root.getPos())
        self.hole.setZ(0.02)

    def rockBackAndForth(self, task):
        t = task.startTime + task.time
        angle = math.sin(t) * 20.0
        self.root.setR(angle)
        return task.cont

    def updateDistance(self, distance):
        self.targetDistance = clamp(distance, -1.0, 1.0)

    def updateTask(self, task):
        self.rockBackAndForth(task)
        if self.targetDistance > self.currentT:
            self.currentT += min(0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)
        elif self.targetDistance < self.currentT:
            self.currentT += max(-0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)
        if self.currentT < 0.0:
            self.targetFacing = -90.0
        elif self.currentT > 0.0:
            self.targetFacing = 90.0
        else:
            self.targetFacing = 0.0
        if self.targetFacing > self.currentFacing:
            self.currentFacing += min(10,
                                      self.targetFacing - self.currentFacing)
        elif self.targetFacing < self.currentFacing:
            self.currentFacing += max(-10,
                                      self.targetFacing - self.currentFacing)
        self.root.setH(self.currentFacing)
        return task.cont

    def setAlongSpline(self, t):
        t = t + 1.0
        dist = (self.endPoint.getX() - self.startPoint.getX()) / 2.0
        x = self.startPoint.getX() + t * dist
        y = self.startPoint.getY() - math.sin(
            t * 2 * math.pi) * self.sinAmplitude
        self.root.setPos(x, y, 0)

    def startBounce(self):
        taskMgr.add(self.bounce, 'PartyCog.bounceTask-%d' % self.id)

    def bounce(self, task):
        self.root.setZ(
            math.sin((self.bounceOffset + task.time) * self.bounceSpeed) *
            self.bounceHeight + self.heightShift)
        return task.cont

    def setPos(self, position):
        self.root.setPos(position)

    def respondToPieHit(self, timestamp, position, hot=False, direction=1.0):
        if self.netTimeSentToStartByHit < timestamp:
            self.__showSplat(position, direction, hot)
            if self.netTimeSentToStartByHit < timestamp:
                self.netTimeSentToStartByHit = timestamp
        else:
            self.notify.debug(
                'respondToPieHit self.netTimeSentToStartByHit = %s' %
                self.netTimeSentToStartByHit)

    def clearHitInterval(self):
        if self.hitInterval is not None and self.hitInterval.isPlaying():
            self.hitInterval.clearToInitial()
        return

    def __showSplat(self, position, direction, hot=False):
        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.clearHitInterval()
        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splat.reparentTo(render)
        self.splat.setPos(self.root, position)
        self.splat.setAlphaScale(1.0)
        if not direction == 1.0:
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[0])
            if self.currentFacing > 0.0:
                facing = 'HitFront'
            else:
                facing = 'HitBack'
        else:
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[1])
            if self.currentFacing > 0.0:
                facing = 'HitBack'
            else:
                facing = 'HitFront'
        if hot:
            targetscale = 0.75
            part = 'head'
        else:
            targetscale = 0.5
            part = 'body'

        def setSplatAlpha(amount):
            self.splat.setAlphaScale(amount)

        self.hitInterval = Sequence(
            ActorInterval(self.actor, part + facing, loop=0),
            Func(self.actor.loop, 'idle'))
        self.hitInterval.start()
        self.kaboomTrack = Parallel(
            SoundInterval(self.pieHitSound,
                          volume=1.0,
                          node=self.actor,
                          cutOff=PartyGlobals.PARTY_COG_CUTOFF),
            Sequence(
                Func(self.splat.showThrough),
                Parallel(
                    Sequence(
                        LerpScaleInterval(self.splat,
                                          duration=0.175,
                                          scale=targetscale,
                                          startScale=Point3(0.1, 0.1, 0.1),
                                          blendType='easeOut'), Wait(0.175)),
                    Sequence(
                        Wait(0.1),
                        LerpFunc(setSplatAlpha,
                                 duration=1.0,
                                 fromData=1.0,
                                 toData=0.0,
                                 blendType='easeOut'))),
                Func(self.splat.cleanup), Func(self.splat.removeNode)))
        self.kaboomTrack.start()
        return

    def showHitScore(self, number, scale=1):
        if number <= 0:
            return
        if self.hpText:
            self.hideHitScore()
        self.HpTextGenerator.setFont(ToontownGlobals.getSignFont())
        if number < 0:
            self.HpTextGenerator.setText(str(number))
        else:
            self.HpTextGenerator.setText('+' + str(number))
        self.HpTextGenerator.clearShadow()
        self.HpTextGenerator.setAlign(TextNode.ACenter)
        r = 1
        g = 1
        b = 0
        a = 1
        self.HpTextGenerator.setTextColor(r, g, b, a)
        self.hpTextNode = self.HpTextGenerator.generate()
        self.hpText = render.attachNewNode(self.hpTextNode)
        self.hpText.setScale(scale)
        self.hpText.setBillboardPointEye()
        self.hpText.setBin('fixed', 100)
        self.hpText.setPos(self.root, 0, 0, self.height / 2)
        seq = Sequence(
            self.hpText.posInterval(
                0.25,
                Point3(self.root.getX(render), self.root.getY(render),
                       self.root.getZ(render) + self.height + 1.0),
                blendType='easeOut'), Wait(0.25),
            self.hpText.colorInterval(0.1, Vec4(r, g, b, 0)),
            Func(self.hideHitScore))
        seq.start()

    def hideHitScore(self):
        if self.hpText:
            taskMgr.remove('PartyCogHpText' + str(self.id))
            self.hpText.removeNode()
            self.hpText = None
        return

    def getHeadLocation(self):
        self.actor.getJoints(jointName='head')[0].getNetTransform(
            self.temp_transform)
        self.head_locator.setMat(self.temp_transform)
        return self.head_locator.getZ(self.root)
Exemple #21
0
class CogdoFlyingLevel(DirectObject):
    notify = directNotify.newCategory('CogdoFlyingLevel')

    def __init__(self, parent, frameModel, startPlatformModel, endPlatformModel, quadLengthUnits, quadVisibilityAhead, quadVisibiltyBehind):
        self.parent_ = parent
        self.quadLengthUnits = quadLengthUnits
        self._halfQuadLengthUnits = quadLengthUnits / 2.0
        self.quadVisibiltyAhead = quadVisibilityAhead
        self.quadVisibiltyBehind = quadVisibiltyBehind
        self._frameModel = frameModel
        self.root = NodePath('CogdoFlyingLevel')
        self.quadrantRoot = NodePath('QuadrantsRoot')
        self.quadrantRoot.reparentTo(self.root)
        self._startPlatformModel = startPlatformModel
        self._startPlatformModel.reparentTo(self.root)
        self._startPlatformModel.setZ(Globals.Level.StartPlatformHeight)
        self._endPlatformModel = endPlatformModel
        self._endPlatformModel.reparentTo(self.root)
        self._endPlatformModel.setZ(Globals.Level.EndPlatformHeight)
        self.wallR = self._frameModel.find('**/wallR')
        self.wallL = self._frameModel.find('**/wallL')
        self._exit = CogdoGameExit()
        self._exit.reparentTo(self._endPlatformModel)
        loc = self._endPlatformModel.find('**/exit_loc')
        offset = loc.getPos(render)
        self._exit.setPos(render, offset)
        self.quadrants = []
        self.visibleQuadIndices = []
        self._numQuads = 0
        self._currentQuadNum = -1
        self._camera = None
        self._initCollisions()
        self.upLimit = self._frameModel.find('**/limit_up').getZ(render)
        self.downLimit = self._frameModel.find('**/limit_down').getZ(render)
        self.leftLimit = self._frameModel.find('**/limit_left').getX(render) - 30.0
        self.rightLimit = self._frameModel.find('**/limit_right').getX(render) + 30.0
        self.backLimit = -self.quadLengthUnits
        self.forwardLimit = self.quadLengthUnits * 20
        self._frameModel.flattenStrong()
        self.gatherableFactory = CogdoFlyingGatherableFactory()
        self.obstacleFactory = CogdoFlyingObtacleFactory()
        return

    def getExit(self):
        return self._exit

    def getBounds(self):
        return ((self.leftLimit, self.rightLimit), (self.backLimit, self.forwardLimit), (self.downLimit, self.upLimit))

    def getGatherable(self, serialNum):
        for quadrant in self.quadrants:
            for gatherable in quadrant.gatherables:
                if gatherable.serialNum == serialNum:
                    return gatherable

        return None

    def ready(self):
        self.gatherableFactory.destroy()
        del self.gatherableFactory
        self.obstacleFactory.destroy()
        del self.obstacleFactory
        self._initStartEndPlatforms()
        self._frameModel.reparentTo(self.root)
        self.root.reparentTo(self.parent_)
        self.root.stash()

    def _initStartEndPlatforms(self):
        self.startPlatform = CogdoFlyingPlatform(self._startPlatformModel, Globals.Level.PlatformTypes.StartPlatform)
        self.endPlatform = CogdoFlyingPlatform(self._endPlatformModel, Globals.Level.PlatformTypes.EndPlatform)
        self._endPlatformModel.setY(self.convertQuadNumToY(self._numQuads))
        self.backLimit = self._startPlatformModel.getY(render) - Globals.Level.StartPlatformLength * 0.7
        self.forwardLimit = self._endPlatformModel.getY(render) + Globals.Level.EndPlatformLength * 0.7

    def _initCollisions(self):
        self.collPlane = CollisionPlane(Plane(Vec3(0, 0, 1.0), Point3(0, 0, 10)))
        self.collPlane.setTangible(0)
        self.collNode = CollisionNode('fogPlane')
        self.collNode.setIntoCollideMask(OTPGlobals.FloorBitmask)
        self.collNode.addSolid(self.collPlane)
        self.collNodePath = self.root.attachNewNode(self.collNode)
        self.collNodePath.hide()

    def destroy(self):
        del self.collPlane
        self.collNodePath.removeNode()
        del self.collNodePath
        del self.collNode
        for quadrant in self.quadrants:
            quadrant.destroy()

        self._exit.destroy()
        del self._exit
        self.root.removeNode()
        del self.root

    def onstage(self):
        self.root.unstash()
        self.update(0.0)

    def offstage(self):
        self.root.stash()

    def start(self, startTime = 0.0):
        self._startTime = startTime

    def stop(self):
        pass

    def getLength(self):
        return self.quadLengthUnits * self.getNumQuadrants()

    def appendQuadrant(self, model):
        quadrant = CogdoFlyingLevelQuadrant(self._numQuads, model, self, self.root)
        if self._numQuads == 0:
            quadrant.generateGatherables(self._startPlatformModel)
        quadrant.offstage()
        self.quadrants.append(quadrant)
        self._numQuads = len(self.quadrants)

    def getNumQuadrants(self):
        return self._numQuads

    def setCamera(self, camera):
        self._camera = camera

    def getCameraActualQuadrant(self):
        camY = self._camera.getY(render)
        y = self.root.getY(render)
        return self.convertYToQuadNum(camY - y)

    def update(self, dt = 0.0):
        if self._camera is None:
            return
        quadNum = clamp(self.getCameraActualQuadrant(), 0, self._numQuads - 1)
        if quadNum < self._numQuads:
            self.quadrants[quadNum].update(dt)
            if quadNum + 1 < self._numQuads:
                self.quadrants[quadNum + 1].update(dt)
            if quadNum != self._currentQuadNum:
                self._switchToQuadrant(quadNum)
        return

    def _switchToQuadrant(self, quadNum):
        self.visibleQuadIndices = []
        if quadNum >= 0:
            if quadNum > 0:
                self.quadrants[max(quadNum - self.quadVisibiltyBehind, 0)].onstage()
            for i in xrange(quadNum, min(quadNum + self.quadVisibiltyAhead + 1, self._numQuads)):
                self.quadrants[i].onstage()
                self.visibleQuadIndices.append(i)
                if i == 0:
                    self.startPlatform.onstage()
                elif i == self._numQuads - 1:
                    self.endPlatform.onstage()

        self._currentQuadNum = quadNum
        for i in xrange(0, max(self._currentQuadNum - self.quadVisibiltyBehind, 0)) + range(min(self._currentQuadNum + self.quadVisibiltyAhead + 1, self._numQuads), self._numQuads):
            self.quadrants[i].offstage()
            if i == 0:
                self.startPlatform.offstage()
            elif i == self._numQuads - 1:
                self.endPlatform.offstage()

    def convertQuadNumToY(self, quadNum):
        return quadNum * self.quadLengthUnits

    def convertYToQuadNum(self, y):
        return int(y / self.quadLengthUnits)

    def convertCenterYToQuadNum(self, y):
        return self.convertYToQuadNum(y + self._halfQuadLengthUnits)
Exemple #22
0
class Player(object):
    """
        Player is the main actor in the fps game
    """
    FORWARD = Vec3(0,2,0)
    BACK = Vec3(0,-1,0)
    LEFT = Vec3(-1,0,0)
    RIGHT = Vec3(1,0,0)
    FLYUP = Vec3(0,0,1)
    FLYDN = Vec3(0,0,-1)
    STOP = Vec3(0)
    PORTAL_CYCLE = {
        'blue' : 'orange',
        'orange' : 'blue',
        }

    def __init__(self, base, fps, osd):
        self.base = base
        self.fps = fps
        self.osd = osd
        self.speed = RUN_SPEED
        self.walk = self.STOP
        self.readyToJump = False
        self.intoPortal = None
        self.mass = Mass()
        self.origin = self.fps.level.settings.origin
        self.bporigin = (999,999,999)
        self.oporigin = (999,999,999)
        self.current_target = None
        self.canPortal = []
        self.canSetTarget = True
        self.selectedCubes = []
        self.editorTextureStage = TextureStage('editor')
        self.editorSelectedTexture = loader.loadTexture('models/tex/selected.png')
        self.selectingForMulti = False
        # Init functions
        self.loadModel()
        self.makePortals()
        self.setUpCamera()
        if self.fps.editor_mode:
            self.createMouseCollisions()
            self.speed = self.speed * 5
            self.attachEditorControls()
            self.attachEditorTasks()
        else:
            self.createCollisions()
            self.attachStandardControls()
            self.attachStandardTasks()

    def loadModel(self):
        """ make the nodepath for player """
        self.node = NodePath('player')
        self.node.reparentTo(render)
        self.node.setPos(*self.origin)
        self.node.setScale(0.05)
        self.mass.pos = VBase3(self.node.getX(), self.node.getY(), self.node.getZ())

    def makePortals(self):
        # The BLUE CUBE
        bpor = loader.loadModel("cube_nocol")
        bpor.setTag('noportals', '1')
        bpor.reparentTo(render)
        bpor.setPos(*self.bporigin)
        bpor.setScale(0.3,0.02,0.5)
        # The BLUE CUBE's camera
        bbuffer = self.base.win.makeTextureBuffer("B Buffer", 512, 512)
        bbuffer.setSort(-100)
        bcamera = self.base.makeCamera(bbuffer)
        bcamera.node().getLens().setAspectRatio(0.3/0.5)
        bcamera.node().getLens().setFov(15)
        bcamera.reparentTo(bpor)
        bcamera.node().setScene(render)

        # The ORANGE CUBE
        opor = loader.loadModel("cube_nocol")
        opor.setTag('noportals', '1')
        opor.reparentTo(render)
        opor.setPos(*self.oporigin)
        opor.setScale(0.3,0.02,0.5)
        # The ORANGE CUBE's camera
        obuffer = self.base.win.makeTextureBuffer("O Buffer", 512, 512)
        obuffer.setSort(-100)
        ocamera = self.base.makeCamera(obuffer)
        ocamera.node().getLens().setAspectRatio(0.3/0.5)
        ocamera.node().getLens().setFov(15)
        ocamera.reparentTo(opor)
        ocamera.node().setScene(render)

        # Assign the textures
        bpor.setTexture(obuffer.getTexture())
        opor.setTexture(bbuffer.getTexture())
        # Store the portals and theirs cameras
        self.bluePortal = bpor
        self.bluePortal.setHpr(0,90,0)
        self.orangePortal = opor
        self.orangePortal.setHpr(0,-90,0)
        self.bcamera = bcamera
        self.ocamera = ocamera

    def setUpCamera(self):
        """ puts camera at the players node """
        pl =  self.base.cam.node().getLens()
        pl.setFov(70)
        self.base.cam.node().setLens(pl)
        self.base.camera.reparentTo(self.node)
        self.base.camLens.setFov(100)
        if self.fps.editor_mode:
            self.node.lookAt(self.fps.level.cubes_hash.keys()[0])

    def createCollisions(self):
        self.createPlayerCollisions()
        self.createMouseCollisions()
        self.createPortalCollisions()

    def createPlayerCollisions(self):
        """ create a collision solid and ray for the player """
        cn = CollisionNode('player')
        cn.setFromCollideMask(COLLISIONMASKS['geometry'])
        cn.setIntoCollideMask(COLLISIONMASKS['portals'] | COLLISIONMASKS['exit'] | COLLISIONMASKS['lava'])
        cn.addSolid(CollisionSphere(0,0,0,3))
        solid = self.node.attachNewNode(cn)
        # TODO : find a way to remove that, it's the cause of the little
        # "push me left" effect we see sometime when exiting a portal
        self.base.cTrav.addCollider(solid,self.base.pusher)
        self.base.pusher.addCollider(solid,self.node, self.base.drive.node())
        # init players floor collisions
        ray = CollisionRay()
        ray.setOrigin(0,0,-.2)
        ray.setDirection(0,0,-1)
        cn = CollisionNode('playerRay')
        cn.setFromCollideMask(COLLISIONMASKS['player'])
        cn.setIntoCollideMask(BitMask32.allOff())
        cn.addSolid(ray)
        solid = self.node.attachNewNode(cn)
        self.nodeGroundHandler = CollisionHandlerQueue()
        self.base.cTrav.addCollider(solid, self.nodeGroundHandler)
        # init players ceil collisions
        ray = CollisionRay()
        ray.setOrigin(0,0,.2)
        ray.setDirection(0,0,1)
        cn = CollisionNode('playerUpRay')
        cn.setFromCollideMask(COLLISIONMASKS['player'])
        cn.setIntoCollideMask(BitMask32.allOff())
        cn.addSolid(ray)
        solid = self.node.attachNewNode(cn)
        self.ceilGroundHandler = CollisionHandlerQueue()
        self.base.cTrav.addCollider(solid, self.ceilGroundHandler)

    def createMouseCollisions(self):
        # Fire the portals
        firingNode = CollisionNode('mouseRay')
        firingNP = self.base.camera.attachNewNode(firingNode)
        firingNode.setFromCollideMask(COLLISIONMASKS['geometry'])
        firingNode.setIntoCollideMask(BitMask32.allOff())
        firingRay = CollisionRay()
        firingRay.setOrigin(0,0,0)
        firingRay.setDirection(0,1,0)
        firingNode.addSolid(firingRay)
        self.firingHandler = CollisionHandlerQueue()
        self.base.cTrav.addCollider(firingNP, self.firingHandler)

    def createPortalCollisions(self):
        # Enter the portals
        cn = CollisionNode('bluePortal')
        cn.setFromCollideMask(COLLISIONMASKS['portals'])
        cn.setIntoCollideMask(BitMask32.allOff())
        np = self.bluePortal.attachNewNode(cn)
        cn.addSolid(CollisionSphere(0,0,0,2))
        h = CollisionHandlerEvent()
        h.addInPattern('%fn-into-%in')
        h.addOutPattern('%fn-outof-%in')
        self.base.cTrav.addCollider(np, h)
        cn = CollisionNode('orangePortal')
        cn.setFromCollideMask(COLLISIONMASKS['portals'])
        cn.setIntoCollideMask(BitMask32.allOff())
        np = self.orangePortal.attachNewNode(cn)
        cn.addSolid(CollisionSphere(0,0,0,2))
        h = CollisionHandlerEvent()
        h.addInPattern('%fn-into-%in')
        h.addOutPattern('%fn-outof-%in')
        self.base.cTrav.addCollider(np, h)

    def attachCommonControls(self):
        self.base.accept( "z" if AZERTY else "w" , self.addWalk,[self.FORWARD])
        self.base.accept( "z-up" if AZERTY else "w-up" , self.addWalk,[-self.FORWARD] )
        self.base.accept( "s" , self.addWalk,[self.BACK] )
        self.base.accept( "s-up" , self.addWalk,[-self.BACK] )
        self.base.accept( "q" if AZERTY else "a" , self.addWalk,[self.LEFT])
        self.base.accept( "q-up" if AZERTY else "a-up" , self.addWalk,[-self.LEFT] )
        self.base.accept( "d" , self.addWalk,[self.RIGHT] )
        self.base.accept( "d-up" , self.addWalk,[-self.RIGHT] )
        self.base.accept( "r-up" , self.resetPosition )
        self.base.accept( "p-up" , self.showPosition )
        self.base.accept( "b-up" , self.deBug )

    def attachStandardControls(self):
        self.attachCommonControls()
        self.base.accept( "space" , self.__setattr__,["readyToJump",True])
        self.base.accept( "space-up" , self.__setattr__,["readyToJump",False])
        self.base.accept( "c-up" , self.__setattr__,["intoPortal",None] )
        self.base.accept( "e-up" , self.erasePortals )
        self.base.accept( "mouse1" , self.fireBlue )
        self.base.accept( "mouse3" , self.fireOrange )
        # Events
        self.base.accept( "bluePortal-into-player" , self.enterPortal, ["blue"] )
        self.base.accept( "orangePortal-into-player" , self.enterPortal, ["orange"] )
        self.base.accept( "bluePortal-outof-player" , self.exitPortal, ["blue"] )
        self.base.accept( "orangePortal-outof-player" , self.exitPortal, ["orange"] )
        self.base.accept( "levelExit-into-player" , self.levelExit)
        self.base.accept( "lava-into-player" , self.fallIntoLava)

    def attachStandardTasks(self):
        taskMgr.add(self.mouseUpdate, 'mouse-task')
        taskMgr.add(self.moveUpdate, 'move-task')
        taskMgr.add(self.jumpUpdate, 'jump-task')

    def attachEditorControls(self):
        self.attachCommonControls()
        self.base.accept( "space" , self.__setattr__, ['selectingForMulti', 1])
        self.base.accept( "space-up" , self.__setattr__, ['selectingForMulti', 0])
        self.base.accept( "shift-space" , self.__setattr__, ['selectingForMulti', 2])
        self.base.accept( "shift-space-up" , self.__setattr__, ['selectingForMulti', 0])
        self.base.accept( "c-up" , self.clearMultiSelectedCubes)
        self.base.accept( "mouse1" , self.selectCubeForCopy, [1])
        self.base.accept( "wheel_up" , self.selectCubeForChange, [1] )
        self.base.accept( "wheel_down" , self.selectCubeForChange, [-1] )
        self.base.accept( "mouse3" , self.selectCubeForDelete )
        self.base.accept("f11", self.saveLevel)
        self.base.accept("x", self.selectCubeForRectangle)
        self.base.accept("shift-x", self.selectCubeForRectangle, [True])
        self.base.accept("l", self.addLightHere)
        self.base.accept("u", self.fps.level.undo, [1])
        for i in range(1,10):
            self.base.accept( "%i-up" % (i,), self.selectCubeForCopy, [i])
        for key, vec in [("a" if AZERTY else "q", self.FLYUP),("w" if AZERTY else "z", self.FLYDN)]:
            self.base.accept(key, self.addWalk, [vec])
            self.base.accept(key + "-up", self.addWalk, [-vec])

    def attachEditorTasks(self):
        taskMgr.add(self.mouseUpdate, 'mouse-task')
        taskMgr.add(self.moveInEditor, 'move-task')

    def deBug(self):
        import pdb
        pdb.set_trace()
    def showPosition(self):
        print self.node.getPos()
        print self.mass
    def fallIntoLava(self, *args, **kwargs):
        # TODO : sound and message + little delay
        self.erasePortals()
        self.resetPosition()
    def resetPosition(self, *args, **kwargs):
        self.node.setHpr(VBase3(0,0,0))
        self.mass.pos = VBase3(*self.origin)
        self.mass.vel = VBase3(0,0,0)
        self.mass.force = VBase3(0,0,0)
        self.node.setPos(self.mass.pos)
    def erasePortals(self):
        self.bluePortal.setPos(*self.bporigin)
        self.orangePortal.setPos(*self.oporigin)
        self.bluePortal.detachNode()
        self.orangePortal.detachNode()
        self.intoPortal = None
        self.canPortal = []
    #@oldpostracker
    def mouseUpdate(self,task):
        """ this task updates the mouse """
        md = self.base.win.getPointer(0)
        x = md.getX()
        y = md.getY()
        if self.base.win.movePointer(0, self.base.win.getXSize()/2, self.base.win.getYSize()/2):
            self.node.setH(self.node.getH() -  (x - self.base.win.getXSize()/2)*0.1)
            if self.fps.editor_mode:
                self.node.setP(self.node.getP() - (y - self.base.win.getYSize()/2)*0.1)
            else:
                self.base.camera.setP(self.base.camera.getP() - (y - self.base.win.getYSize()/2)*0.1)
            self.canSetTarget = True
            self.bcamera.lookAt(self.bluePortal, self.node.getPos(self.orangePortal))
            self.ocamera.lookAt(self.orangePortal, self.node.getPos(self.bluePortal))
            #self.canPortal = ['blue','orange']
            if self.fps.editor_mode:
                cube, point, normal = self.selectCube()
                self.osd.updateTargetPosition(cube)
        if self.selectingForMulti:
            self.selectCubeForMulti()
        return task.cont

    def addWalk(self, vec):
        self.walk += vec

    def moveUpdate(self,task):
        """ this task makes the player move """
        # move where the keys set it
        self.node.setPos(self.node, self.walk*globalClock.getDt()*self.speed)
        return task.cont

    #@oldpostracker
    def jumpUpdate(self,task):
        """ this task simulates gravity and makes the player jump """
        # get the highest Z from the down casting ray
        highestZ = -100
        lowestZ = 100
        for i in range(self.nodeGroundHandler.getNumEntries()):
            entry = self.nodeGroundHandler.getEntry(i)
            z = entry.getSurfacePoint(render).getZ()
            if z > highestZ and entry.getIntoNode().getName() in ( "CollisionStuff", "Plane", "Cube" ):
                highestZ = z
        for i in range(self.ceilGroundHandler.getNumEntries()):
            entry = self.ceilGroundHandler.getEntry(i)
            z = entry.getSurfacePoint(render).getZ()
            if z < lowestZ and entry.getIntoNode().getName() in ( "CollisionStuff", "Plane", "Cube" ):
                lowestZ = z
        # gravity effects and jumps
        self.mass.simulate(globalClock.getDt())
        self.node.setZ(self.mass.pos.getZ())
        if highestZ > self.node.getZ()-PLAYER_TO_FLOOR_TOLERANCE:
            self.mass.zero()
            self.mass.pos.setZ(highestZ+PLAYER_TO_FLOOR_TOLERANCE)
            self.node.setZ(highestZ+PLAYER_TO_FLOOR_TOLERANCE)
        if lowestZ < self.node.getZ()+PLAYER_TO_FLOOR_TOLERANCE:
            self.mass.zero()
            self.mass.pos.setZ(lowestZ-PLAYER_TO_FLOOR_TOLERANCE)
            self.node.setZ(lowestZ-PLAYER_TO_FLOOR_TOLERANCE)
        if self.readyToJump and self.node.getZ() < highestZ + PLAYER_TO_FLOOR_TOLERANCE_FOR_REJUMP:
            self.mass.jump(JUMP_FORCE)
        return task.cont

    def firePortal(self, name, node):
        def hasTagValue(node, tag, value):
            if node.getTag(tag) == value:
                return True
            for pnum in range(node.getNumParents()):
                return hasTagValue(node.getParent(pnum), tag, value)
            return False
        self.firingHandler.sortEntries()
        if self.firingHandler.getNumEntries() > 0:
            closest = self.firingHandler.getEntry(0)
            if hasTagValue(closest.getIntoNode(), 'noportals', '1'):
                return
            point = closest.getSurfacePoint(render)
            normal = closest.getSurfaceNormal(render)
            node.setPos(point)
            node.lookAt(point + normal)
            node.reparentTo(render)
            dest = self.PORTAL_CYCLE[name]
            if dest not in self.canPortal:
                self.canPortal.append(dest)

    def fireBlue(self, *arg, **kwargs):
        self.firePortal("blue", self.bluePortal)

    def fireOrange(self, *arg, **kwargs):
        self.firePortal("orange", self.orangePortal)

    #@oldpostracker
    def enterPortal(self, color, collision):
        if self.intoPortal is None and color in self.canPortal:
            self.intoPortal = color
            portal = {"orange": self.bluePortal, "blue": self.orangePortal}.get(color)
            otherportal = {"orange": self.orangePortal, "blue": self.bluePortal}.get(color)
            # Handle horizontal portals :
            if portal.getH() == 0:
                self.node.setP(0)
                self.node.setR(0)
            elif otherportal.getH() == 0:
                self.node.setH(portal.getH())
                self.node.setP(0)
                self.node.setR(0)
            else:
                # New HPR is relative to 'new' portal but it the 'same' value
                # as the old HPR seen from the 'other' portal
                oldh_fromportal = self.node.getH(otherportal)
                self.node.setHpr(Vec3(0,0,0))
                self.node.setH(portal, 180-oldh_fromportal)
                newh_fromportal = self.node.getH(portal)
            self.node.setPos(portal, self.walk * 10.)
            self.mass.pos = self.node.getPos()
            # Make half a turn (only if we straffing without walking)
            if self.walk.getY() == 0 and self.walk.getX() != 0:
                self.node.setH(self.node, 180)
                self.node.setPos(self.node, self.walk * 10)
    #@oldpostracker
    def exitPortal(self, color, collision):
        # When you entered the blue portal, you have to exit the orange one
        if self.intoPortal != color:
            self.intoPortal = None

    def levelExit(self, event):
        if self.fps.level.settings.next_level:
            self.fps.level.loadlevel(self.fps.level.settings.next_level)
            self.origin = self.fps.level.settings.origin
            self.resetPosition()
            self.erasePortals()
            self.walk = self.STOP
        else:
            print "You won !"
            sys.exit(0)

    # EDITOR MODE
    def selectCube(self):
        self.firingHandler.sortEntries()
        if self.firingHandler.getNumEntries() > 0:
            closest = self.firingHandler.getEntry(0)
            return closest.getIntoNodePath().getParent().getParent(), closest.getSurfacePoint(render), closest.getSurfaceNormal(render) # render/cube.egg/-PandaNode/-GeomNode
        else:
            return None, None, None

    def clearMultiSelectedCubes(self):
        for c in self.selectedCubes:
            c.clearTexture(self.editorTextureStage)
        self.selectedCubes = []

    def selectCubeForMulti(self):
        cube, point, normal = self.selectCube()
        if cube:
            if self.selectingForMulti == 1:
                cube.setTexture(self.editorTextureStage, self.editorSelectedTexture)
                if cube not in self.selectedCubes:
                    self.selectedCubes.append(cube)
            elif cube in self.selectedCubes:
                cube.clearTexture(self.editorTextureStage)
                self.selectedCubes.remove(cube)

    def selectCubeForCopy(self, qty = 1):
        cube, point, normal = self.selectCube()
        if not (cube and point and normal):
            return
        if self.selectedCubes:
            for c in self.selectedCubes:
                self.fps.level.copyCube(c, normal, qty)
            self.clearMultiSelectedCubes()
        else:
            self.fps.level.copyCube(cube, normal, qty)

    def selectCubeForDelete(self):
        cube, point, normal = self.selectCube()
        if not (cube and point and normal):
            return
        if self.selectedCubes:
            for c in self.selectedCubes:
                self.fps.level.deleteCube(c)
            self.clearMultiSelectedCubes()
        else:
            self.fps.level.deleteCube(cube)

    def selectCubeForChange(self, step = 1):
        cube, point, normal = self.selectCube()
        if not (cube and point and normal):
            return
        if self.selectedCubes:
            for c in self.selectedCubes:
                self.fps.level.changeCube(c, step)
        else:
            self.fps.level.changeCube(cube, step)

    def selectCubeForRectangle(self, makeRoom = False):
        cube, point, normal = self.selectCube()
        if makeRoom:
            self.fps.level.createRoom(cube, self.node) # creates a room from the selected cube to the player(camera) position
        else:
            self.fps.level.createRectangle(cube, self.node) # creates a rectangle from the selected cube to the player(camera) position

    def saveLevel(self):
        camerapos = [self.node.getX(), self.node.getY(), self.node.getZ()]
        levelname = self.fps.levelname
        self.fps.level.savelevel(levelname, camerapos)

    def addLightHere(self):
        camerapos = [self.node.getX(), self.node.getY(), self.node.getZ()]
        self.fps.level.addLightHere(camerapos)

    def moveInEditor(self,task):
        self.node.setPos(self.node, self.walk*globalClock.getDt()*self.speed)
        self.osd.updatePosition(self.node)
        return task.cont
Exemple #23
0
class Character(DirectObject, XMLExportable, PropertiesTableAbstract, GameEntity, Pausable):
    
    def __init__(self, attributes, showCollisions, grid_currentx, grid_currenty, grid_playable_pos, parent):
        GameEntity.__init__(self, parent) #running parent constructor
        
        self.playable = False #defaulting to false
        self.cinematic = False #defaulting to false
        self.footSound = None
        self.movtask = 0
        self.showCollisions = showCollisions
        self.grid_currentx = grid_currentx
        self.grid_currenty = grid_currenty
        self.grid_playable_pos = grid_playable_pos
        self.attributes = attributes
        self.onPicked = ''
        self.onWalked = ''
        self.typeName = 'character'
        
        self.properties = {
            'url' : '',
            'onWalked' : '',
            'onPicked' : '',
            'id' : '',
            'inclination' : '',
            'scale' : '',
            'hitboxscale' : '',
            'speed' : '',
            'playable' : '',
            'direction' : '',
            'footsteps' : ''
        }
        
        self.propertiesUpdateFactor = {
            'inclination' : 0.2,
            'scale' : 0.1,
            'hitboxscale' : 0.1,
            'speed' : 0.1
        }
        
        if attributes.has_key('url'):
            self.properties['url'] = attributes['url'].value
        else:
            print "WARNING: url not defined, loading placeholder"
            self.properties['url'] = 'misc/placeholder'
        
        if attributes.has_key('id'):
            self.properties['id'] = attributes['id'].value
        else:
            self.properties['id'] = 'all'
        
        if attributes.has_key('inclination'):
            self.properties['inclination'] = float(attributes['inclination'].value)
        else:
            self.properties['inclination'] = 2.0
        
        if attributes.has_key('scale'):
            self.properties['scale'] = float(attributes['scale'].value)
        else:
            self.properties['scale'] = 1.0
        
        if attributes.has_key('hitboxscale'):
            self.properties['hitboxscale'] = float(attributes['hitboxscale'].value)
        else:
            self.properties['hitboxscale'] = 1.0
        
        if attributes.has_key('speed'):
            self.properties['speed'] = float(attributes['speed'].value)
        else:
            self.properties['speed'] = 1.0
        
        #self.isNPC remains true while isPlayable is changable
        if attributes.has_key('playable'):
            self.playable = playable = attributes['playable'].value
            if self.playable == 'false':                
                self.isNPC = False
                #print "setting ", self.properties['id'], " to ", self.isNPC
            else:
                self.isNPC = True
                #print "setting ", self.properties['id'], " to ", self.isNPC
        else:
            self.playable = playable = 'false'
            self.isNPC = True
        self.properties['playable'] = self.playable
        
        
        if attributes.has_key('direction'):
            self.properties['direction'] = attributes['direction'].value
        else:
            self.properties['direction'] = "down"
        
        if attributes.has_key('footsteps'):
            self.properties['footsteps'] = attributes['footsteps'].value
        else:
            self.properties['footsteps'] = "sfx/footsteps_default0.ogg"
        
        if attributes.has_key('onWalked'):
            self.properties['onWalked'] = self.onWalked = attributes['onWalked'].value
        else:
            self.properties['onWalked'] = self.onWalked = ""
        
        if attributes.has_key('onPicked'):
            self.properties['onPicked'] = self.onPicked = attributes['onPicked'].value
        
        self.generateNode(showCollisions)
        
    def generateNode(self, showCollisions):
        self.destroy()
        
        #setting local variable
        attributes = self.attributes
        
        #defaulted to None
        self.pickCTrav = None
        
        #movement
        self.state = "still"
        self.showCollisions = showCollisions
        
        self.movtask = 0
        self.currentlydown = []
        self.currentlyfollowed = 0
        
        self.pickRequest = False
        
        #public props
        self.node = NodePath("characternode")
        self.node.setTwoSided(True)
        
        self.wtop = self.applyNearestFilter(loader.loadModel(resourceManager.getResource(self.properties['url'])+'/wtop.egg'))
        self.wdown = self.applyNearestFilter(loader.loadModel(resourceManager.getResource(self.properties['url'])+'/wdown.egg'))
        self.wleft = self.applyNearestFilter(loader.loadModel(resourceManager.getResource(self.properties['url'])+'/wleft.egg'))
        self.wright = self.applyNearestFilter(loader.loadModel(resourceManager.getResource(self.properties['url'])+'/wright.egg'))
        self.stop = self.applyNearestFilter(loader.loadModel(resourceManager.getResource(self.properties['url'])+'/stop.egg'))
        self.sdown = self.applyNearestFilter(loader.loadModel(resourceManager.getResource(self.properties['url'])+'/sdown.egg'))
        self.sleft = self.applyNearestFilter(loader.loadModel(resourceManager.getResource(self.properties['url'])+'/sleft.egg'))
        self.sright = self.applyNearestFilter(loader.loadModel(resourceManager.getResource(self.properties['url'])+'/sright.egg'))
        
        #Texture.FTNearest
        
        self.wtop.reparentTo(self.node)
        self.wdown.reparentTo(self.node)
        self.wleft.reparentTo(self.node)
        self.wright.reparentTo(self.node)
        self.stop.reparentTo(self.node)
        self.sdown.reparentTo(self.node)
        self.sleft.reparentTo(self.node)
        self.sright.reparentTo(self.node)
        
        self.leftdown = False
        self.rightdown = False
        self.downdown = False
        self.topdown = False
        
        if self.playable=="true":
            self.setPlayable(False) #seems nonsense, triggered on grid.changeMap event
            self.node.setTag("playable", "true") #setting this to make it recognizable from grid changeMap api
            self.setCollisions(True)
            self.setPickCollisions(True)
        else:
            self.setPlayable(False)
            self.node.setTag("playable", "false")
            self.setCollisions(False)
            self.setPickCollisions(False)
        
        #self.node.setX((-32/2)+0.5)
        self.node.setP(-(360-int(self.properties['inclination'])))
        self.node.setScale(float(self.properties['scale']))
        self.node.setTransparency(TransparencyAttrib.MAlpha)
        
        self.lastpos = self.node.getPos()
        
        self.showAllSubnodes()
        
        #taskMgr.doMethodLater(4, self.face, 'charload'+self.properties['id'], [self.properties['direction']])
        self.face(self.properties['direction'])
        
        #set unique id
        self.node.setTag("id", self.properties['id'])
        #setting scripting part
        self.node.setTag("onWalked", self.onWalked)
        self.node.setTag("onPicked", self.onPicked)
        
        #storing a pointer of the gamenode
        self.node.setPythonTag("gamenode", self)
        
        self.npc_walk_stack = []
        self.npc_walk_happening = False
        self.globalLock = False
        
        self.setX(self.grid_currentx)
        self.setY(self.grid_currenty)
        
        if self.isNPC!=True:
            print "attempting creation of NPC in ", self.grid_currentx, "-", self.grid_currenty
        
        if self.properties['footsteps'] != "":
            path = resourceManager.getResource(self.properties['footsteps'])
            self.footSound = base.loader.loadSfx(path)
            self.footSound.setVolume(0.75)
            self.footSound.setLoop(True)
        
        if attributes.has_key('playable'):
            if self.isNPC!=False:
                if ((self.grid_playable_pos.getX() != 0) and (self.grid_playable_pos.getY() != 0)):
                    #print 'GRID: moving player to ' + str(self.grid_playable_pos)
                    self.setX(self.grid_playable_pos.getX())
                    self.setY(self.grid_playable_pos.getY())
        
        #automatic reparenting (and showing) when (re)generating node
        self.node.wrtReparentTo(self.parent.node)
    
    def getName(self):
        return 'Character: '+self.properties['id']
    
    def xmlAttributes(self):
        return self.properties
    
    def xmlTypeName(self):
        return self.typeName
    
    '''
    Sanitize properties data to be of correct type from string
    '''
    def sanitizeProperties(self):
        #sanitizing data
        self.properties['inclination'] = float(self.properties['inclination'])
        self.properties['hitboxscale'] = float(self.properties['hitboxscale'])
        self.properties['speed'] = float(self.properties['speed'])
        self.properties['scale'] = float(self.properties['scale'])
        
        self.updateTilePosition()
    
    #interface needed by PropertiesTable
    # regenerates the node at every change
    def onPropertiesUpdated(self):
        self.sanitizeProperties()
        self.generateNode(self.showCollisions)
        
    
    #interface needed by PropertiesTable
    #TODO: implement as real interface?
    def getPropertyList(self):
        return self.properties
    
    #interface needed by PropertiesTable
    def setProperty(self, key, value):
        self.properties[key] = value
    
    def increaseProperty(self, key, multiplier):
        if key in self.propertiesUpdateFactor:
            self.setProperty(key, self.properties[key]+self.propertiesUpdateFactor[key]*multiplier)
        
    def decreaseProperty(self, key, multiplier):
        if key in self.propertiesUpdateFactor:
            self.setProperty(key, self.properties[key]-self.propertiesUpdateFactor[key]*multiplier)
    
    def copyProperties(self):
        return self.getPropertyList()
    
    def pasteProperties(self, props):
        for key, value in props.iteritems():
            if key in self.properties:
                self.properties[key] = value
        self.onPropertiesUpdated()
    
    def setSpeed(self, s):
        self.properties['speed'] = s
    
    def applyNearestFilter(self, model):
        for tex in model.findAllTextures():
            tex.setMinfilter(Texture.FT_nearest)
            tex.setMagfilter(Texture.FT_nearest)
        return model
    
    def startFootsteps(self):
        if self.footSound != None:
            self.footSound.play()
    
    def stopFootsteps(self):
        if self.footSound != None:
            self.footSound.stop()
    
    '''
    make the npc walk in direction for units
    '''
    def npc_push_walk(self, direction, units):
        #locking script execution
        self.globalLock = True
        script.addOneCustomLock(self)
        
        #start the walking
        self.npc_walk_stack.append([direction, units])
        self.npc_walk_helper()
        
    #apicall
    def npc_walk_helper(self):
        x = self.node.getX()
        y = self.node.getZ()
        
        #concurrent protection
        if self.npc_walk_happening == True:
            return
        
        #returning if no movement has to be performed
        if len(self.npc_walk_stack) < 0:
            return
        
        movement = self.npc_walk_stack.pop(0)
        
        direction = movement[0]
        units = movement[1]
        
        self.npc_targetx = x
        self.npc_targety = y
        self.npc_direction = direction
        
        if(direction=="down"):
            self.npc_targety = self.npc_targety - units
        elif(direction=="up"):
            self.npc_targety = self.npc_targety + units
        elif(direction=="left"):
            self.npc_targetx = self.npc_targetx - units
        elif(direction=="right"):
            self.npc_targetx = self.npc_targetx + units
        
        self.setAnim(direction)
        
        self.npc_walk_happening = True
        self.npc_movtask = taskMgr.add(self.npc_walk_task, "npc_moveCharacterTask"+self.properties['id'], uponDeath=self.npc_walk_callback)
        #footsteps call
        self.startFootsteps()
    
    def npc_walk_task(self, task):
        dt = globalClock.getDt()
        
        if(self.npc_direction=='left'):
            self.node.setX(self.node.getX()-1*dt*self.properties['speed'])
            currentx = self.node.getX()
            
            if currentx <= self.npc_targetx:
                return task.done
        if(self.npc_direction=='right'):
            self.node.setX(self.node.getX()+1*dt*self.properties['speed'])
            currentx = self.node.getX()
            
            if currentx >= self.npc_targetx:
                return task.done
        if(self.npc_direction=='up'):
            self.node.setZ(self.node.getZ()+1*dt*self.properties['speed'])
            currenty = self.node.getZ()
            
            if currenty >= self.npc_targety:
                return task.done
        if(self.npc_direction=='down'):
            self.node.setZ(self.node.getZ()-1*dt*self.properties['speed'])
            currenty = self.node.getZ()
            
            if currenty <= self.npc_targety:
                return task.done
        
        return task.cont
    
    def setCinematic(self, value):
        self.cinematic = value
    
    '''
    Resume past state of playable when
    resumeGameplay is catched 
    '''
    def resumeGameplay(self):
        self.setPlayable(True)
    
    
    '''
    Resume past state of playable when
    resumeGameplay is catched 
    '''
    def pauseGameplay(self):
        self.setPlayable(False)
    
    
    def npc_walk_callback(self, task):
        self.face(self.npc_direction)
        
        #unlocking concurrent movement protection
        self.npc_walk_happening = False
        
        #stopping footsteps
        self.stopFootsteps()
        
        if len(self.npc_walk_stack) > 0:
            self.npc_walk_helper()
        else: #character ended walking, unlock
            self.globalLock = False
            
    
    '''
    write destroy function
    '''
    def destroy(self):
        #not accepting events
        self.ignoreAll()
        #destroying everything down
        if self.node != None:
            self.node.remove_node()
        #removing all tasks
        if self.movtask != 0:
            taskMgr.remove(self.movtask)
            self.movtask = 0
    
    def face(self, direction):
        if direction == "left":
            self.hideAllSubnodes()
            self.sleft.show()
        if direction == "right":
            self.hideAllSubnodes()
            self.sright.show()
        if direction == "top" or direction == "up": #let's keep retrocompatibility
            self.hideAllSubnodes()
            self.stop.show()
        if direction == "down":
            self.hideAllSubnodes()
            self.sdown.show()
    
    def setCollisions(self, value):
        if value == True:
            b = self.node.getBounds().getRadius()
            
            self.cTrav = CollisionTraverser()
            
            self.collisionTube = CollisionSphere(b/2,0,b/2,0.035*self.properties['hitboxscale'])
            self.collisionNode = CollisionNode('characterTube')
            self.collisionNode.addSolid(self.collisionTube)
            self.collisionNodeNp = self.node.attachNewNode(self.collisionNode)
            self.collisionHandler = CollisionHandlerQueue()
            self.cTrav.addCollider(self.collisionNodeNp, self.collisionHandler)
            
            if self.showCollisions == True or main.editormode:
                # Uncomment this line to see the collision rays
                self.collisionNodeNp.show()
                
                # Uncomment this line to show a visual representation of the 
                # collisions occuring
                self.cTrav.showCollisions(render)
        else:
            b = self.node.getBounds().getRadius()
            self.collisionTube = CollisionSphere(b/2,0,b/2,0.035*self.properties['hitboxscale'])
            
            #allowing playables to collide with npcs
            if self.isNPC == True: #TODO: fix because it's completely f****d up
                self.collisionNode = CollisionNode('characterTube')
            else:
                self.collisionNode = CollisionNode('characterNPCTube')
            
            self.collisionNode.addSolid(self.collisionTube)
            self.collisionNodeNp = self.node.attachNewNode(self.collisionNode)
    
    #set if camera has to effectively follow the character
    #while it moves
    def setFollowedByCamera(self, value):
        #camera follow
        if value:
            if self.currentlyfollowed!=True:
                customCamera.follow(self)
                self.currentlyfollowed = True
        else:
            if self.currentlyfollowed!=False:
                customCamera.dontFollow()
                self.currentlyfollowed = False
    
    def setPickCollisions(self, value):
        if value:
            print "setting pick collisions"
            b = self.node.getBounds().getRadius()
            
            self.pickCTrav = CollisionTraverser()
            
            self.pickCollisionTube = CollisionSphere(b/2,0,b/2,0.035*self.properties['hitboxscale']+0.01)
            self.pickCollisionNode = CollisionNode('characterPickTube')
            self.pickCollisionNode.addSolid(self.pickCollisionTube)
            self.pickCollisionNodeNp = NodePath(self.pickCollisionNode)
            self.pickCollisionNodeNp.reparentTo(self.node)
            self.pickCollisionHandler = CollisionHandlerQueue()
            self.pickCTrav.addCollider(self.pickCollisionNodeNp, self.pickCollisionHandler)
            
            
            
            if self.showCollisions == True:
                # Uncomment this line to see the collision rays
                self.pickCollisionNodeNp.show()
                
                # Uncomment this line to show a visual representation of the 
                # collisions occuring
                self.pickCTrav.showCollisions(render)
        else:
            #dereferincing all pick colliders (must be done in order not to collide onto NPCs)
            self.pickCTrav = None
            self.pickCollisionTube = None
            self.pickCollisionNode = None
            self.pickCollisionNodeNp = None
            self.pickCollisionHandler = None
            
    
    #used to set playability in real time
    #useful when we want to switch context/scripted scenes
    def setPlayable(self, value):
        if self.cinematic == True:
            value = False
        if self.isNPC != False:
            if value == True:
                self.playable = True
                #down events
                self.accept("arrow_left", self.arrowLeftDown)
                self.accept("arrow_right", self.arrowRightDown)
                self.accept("arrow_up", self.arrowUpDown)
                self.accept("arrow_down", self.arrowDownDown)
                #up events
                self.accept("arrow_left-up", self.arrowLeftUp)
                self.accept("arrow_right-up", self.arrowRightUp)
                self.accept("arrow_up-up", self.arrowUpUp)
                self.accept("arrow_down-up", self.arrowDownUp)
                self.accept("space", self.spaceDown)
                self.node.setTag("playable", "true")
                self.setFollowedByCamera(True)
                self.accept("pauseGameplay", self.pauseGameplay) #can pause play
            else:
                self.playable = False
                self.ignoreAll()
                self.node.setTag("playable", "false")
                self.setFollowedByCamera(False)
                self.resetMovement() #reset every movement happening
                self.accept("resumeGameplay", self.resumeGameplay) #can resume play if not NPC
    
    #estimate loading time 4 seconds... lol... UPDATE: seems fixed in newer panda versions, inspect
    def showAllSubnodes(self):
        self.wtop.show()
        self.wdown.show()
        self.wleft.show()
        self.wright.show()
        self.stop.show()
        self.sdown.show()
        self.sleft.show()
        self.sright.show()
        
    
    def hideAllSubnodes(self):
        self.wtop.hide()
        self.wdown.hide()
        self.wleft.hide()
        self.wright.hide()
        self.stop.hide()
        self.sdown.hide()
        self.sleft.hide()
        self.sright.hide()
    
    def setMovement(self, value):
        if value == True:
            self.startFootsteps() #playing footsteps
            if self.movtask == 0:
                self.movtask = taskMgr.add(self.moveCharacter, "moveCharacterTask")
        if value == False:
            self.stopFootsteps() #stopping footsteps
            if self.movtask != 0:
                if len(self.currentlydown) == 0:
                    taskMgr.remove(self.movtask)
                    self.movtask = 0
    
    '''
    reset every movement actually happening
    '''
    def resetMovement(self):
        if self.leftdown == True:
            self.face("left")
        if self.rightdown == True:
            self.face("right")
        if self.downdown == True:
            self.face("down")
        if self.topdown == True:
            self.face("top")
        
        self.leftdown = False
        self.rightdown = False
        self.downdown = False
        self.topdown = False
        
        self.currentlydown = []
        
        self.setMovement(False)
    
    def setAnim(self, direction=''):
        self.hideAllSubnodes()
        
        if direction=='':        
            if len(self.currentlydown) > 0:
                if self.currentlydown[-1] == 'left':
                    self.wleft.show()
                if self.currentlydown[-1] == 'right':
                    self.wright.show()
                if self.currentlydown[-1] == 'top':
                    self.wtop.show()
                if self.currentlydown[-1] == 'down':
                    self.wdown.show()
        else:
            if direction=='left':
                self.wleft.show()
            if direction=='right':
                self.wright.show()
            if direction=='up':
                self.wtop.show()
            if direction=='down':
                self.wdown.show()
    
    #pick request function
    def spaceDown(self):
        self.pickRequest = True
        
    #movement related functions
    def arrowLeftDown(self):
        #track key down
        self.leftdown = True
        self.setMovement(True)
        #show changes to screen
        self.currentlydown.append("left")
        self.setAnim()
    def arrowLeftUp(self):
        self.leftdown = False
        self.setMovement(False)
        #show changes to screen
        if len(self.currentlydown) == 1:
            self.hideAllSubnodes()
            self.sleft.show()
        if "left" in self.currentlydown:
            self.currentlydown.remove("left")
        
        if len(self.currentlydown) > 0:
            self.setAnim()
    
    def arrowRightDown(self):
        #track key down
        self.rightdown = True
        self.setMovement(True)
        #show changes to screen
        self.currentlydown.append("right")
        self.setAnim()
    def arrowRightUp(self):
        self.setMovement(False)
        self.rightdown = False
        #show changes to screen
        if len(self.currentlydown) == 1:
            self.hideAllSubnodes()
            self.sright.show()
        if "right" in self.currentlydown:
            self.currentlydown.remove("right")
        
        if len(self.currentlydown) > 0:
            self.setAnim()
    
    def arrowDownDown(self):
        #track key down
        self.downdown = True
        self.setMovement(True)
        #show changes to screen
        self.currentlydown.append("down")
        self.setAnim()
    def arrowDownUp(self):
        self.downdown = False
        self.setMovement(False)
        #show changes to screen
        if len(self.currentlydown) == 1:
            self.hideAllSubnodes()
            self.sdown.show()
        if "down" in self.currentlydown:
            self.currentlydown.remove("down")
        
        if len(self.currentlydown) > 0:
            self.setAnim()
    
    def arrowUpDown(self):
        #track key down
        self.topdown = True
        self.setMovement(True)
        #show changes to screen
        self.currentlydown.append("top")
        self.setAnim()
    def arrowUpUp(self):
        self.topdown = False
        self.setMovement(False)
        #show changes to screen
        if len(self.currentlydown) == 1:
            self.hideAllSubnodes()
            self.stop.show()
        if "top" in self.currentlydown:
            self.currentlydown.remove("top")
        if len(self.currentlydown) > 0:
            self.setAnim()
    
    def moveCharacter(self, task):
        dt = globalClock.getDt()
        if len(self.currentlydown) > 0:
            if self.currentlydown[-1] == 'left':
                self.node.setX(self.node.getX()-1*dt*self.properties['speed'])
            if self.currentlydown[-1] == 'right':
                self.node.setX(self.node.getX()+1*dt*self.properties['speed'])
            if self.currentlydown[-1] == 'top':
                self.node.setZ(self.node.getZ()+1*dt*self.properties['speed'])
            if self.currentlydown[-1] == 'down':
                self.node.setZ(self.node.getZ()-1*dt*self.properties['speed'])
        
        #check collisions
        if self.cTrav != None:
            self.cTrav.traverse(render)
        
        if self.pickCTrav != None:
            self.pickCTrav.traverse(render)
        
        #entries python list
        entries = list(self.collisionHandler.getEntries())
        pickentries = list(self.pickCollisionHandler.getEntries())
        
        for e in entries[:]:
            if e.getIntoNodePath().getName() == "characterPickTube":
                entries.remove(e)
        
        for e in pickentries[:]:
            if e.getIntoNodePath().getName() == "characterTube":
                pickentries.remove(e)
        
        if len(entries) == 0:
            self.lastpos = self.node.getPos()
        else:
            sp = entries[0].getSurfacePoint(self.node) #surface point
            objectNode = entries[0].getIntoNodePath().getParent() #into object node
            groundNode = entries[0].getIntoNodePath() #into object node
            
            if objectNode.hasTag("collideandwalk"):
                if objectNode.getTag("collideandwalk") != "yes":
                    self.node.setPos(self.lastpos)
            else:
                self.node.setPos(self.lastpos)
            
            #if node is a real object (not a wall)
            if objectNode.hasTag("avoidable"):
                if objectNode.getTag("avoidable") == "true": #see if object is intelligently avoidable
                    if objectNode.hasTag("xscaled") and objectNode.hasTag("yscaled"):
                        if len(self.currentlydown) > 0: #at least 1, avoids list index out of range exception
                            if self.currentlydown[-1] == 'left' or self.currentlydown[-1] == 'right': #TODO: fix the shiet, not always working
                                bottomObjPos = objectNode.getZ()-(float(objectNode.getTag("yscaled"))/2)
                                topObjPos = objectNode.getZ()+(float(objectNode.getTag("yscaled"))/2)
                                if self.node.getZ() < bottomObjPos:
                                    self.node.setZ(self.node.getZ()-1*dt*self.properties['speed'])
                                if self.node.getZ() > topObjPos:
                                    self.node.setZ(self.node.getZ()+1*dt*self.properties['speed'])
                                pass
                            if self.currentlydown[-1] == 'top' or self.currentlydown[-1] == 'down':
                                leftObjPos = objectNode.getX()-(float(objectNode.getTag("xscaled"))/2)
                                rightObjPos = objectNode.getX()+(float(objectNode.getTag("xscaled"))/2)
                                
                                if self.node.getX() < leftObjPos:
                                    self.node.setX(self.node.getX()-1*dt*self.properties['speed'])
                                    
                                if self.node.getX() > rightObjPos:
                                    self.node.setX(self.node.getX()+1*dt*self.properties['speed'])
                            self.lastpos = self.node.getPos()
            
        
        for entry in entries:
            objectNode = entry.getIntoNodePath().getParent()
            onWalked = objectNode.getTag("onWalked")
            if len(onWalked)>0:
                eval(onWalked) #oh lol, danger detected here
        
        evaluatedOnce = False
        if self.pickRequest == True:
            for entry in pickentries:
                objectNode = entry.getIntoNodePath().getParent()
                onPicked = objectNode.getTag("onPicked")
                if len(onPicked)>0 and evaluatedOnce == False:
                    eval(onPicked) #oh lol, danger detected again here
                    evaluatedOnce = True
                else:
                    if hasattr(objectNode.getPythonTag('gamenode'), 'name'):
                        print "WARNING: picking on this object is not defined: ", objectNode.getPythonTag('gamenode').name
                        print "X: ",objectNode.getX()
                        print "Y: ",objectNode.getZ()
            self.pickRequest = False #resetting request
        
        #this is needed for empty pick
        if self.pickRequest == True:
            self.pickRequest = False #resetting request
        
        return Task.cont
    
    def getX(self):
        return self.node.getX()
        
    def getY(self):
        return self.node.getY()
    
    def getZ(self):
        return self.node.getZ()
    
    def getNode(self):
        return self.node
    
    def getWorldPos(self):
        return self.node.getPos(render)
    
    def setX(self, x):
        self.node.setX(x)
        self.lastpos.setX(x)
    
    def setY(self, y):
        self.node.setZ(y)
        self.lastpos.setZ(y)
    
    #here for polymorph
    def getTileX(self):
        return self.parent.getX()
    
    #here for polymorph
    def getTileY(self):
        return self.parent.getY()