Ignore:
Timestamp:
06/25/10 18:01:54 (9 years ago)
Author:
beliar
Message:

Ticket #200: Patch by Beliar.

  • Merging map_loading_change branch back into trunk

fixes[s:trac, t:200]

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

    • Property svn:ignore
      •  

        old new  
         1*.pyc 
         2.project 
         3.pydevproject 
        14Thumbs.db 
        2 *.pyc 
    • Property svn:mergeinfo changed
      /branches/map_loading_change (added)merged: 554-562
  • trunk/game/scripts/gamemodel.py

    r553 r563  
    1919import pickle 
    2020import sys 
     21import os.path 
    2122from gamestate import GameState 
    2223from objects import createObject 
    23 from map import Map 
     24from objects.composed import CarryableItem 
     25from gamemap import GameMap 
    2426from fife import fife 
     27from common.utils import locateFiles 
     28from common.utils import parseBool 
     29from inventory import Inventory 
     30try: 
     31    import xml.etree.cElementTree as ElementTree 
     32except ImportError: 
     33    import xml.etree.ElementTree as ElementTree 
    2534 
    2635import yaml 
     
    3241       the fife view here. This also prevents us from just having a 
    3342       function heavy controller.""" 
    34     def __init__(self, engine): 
     43    ALL_AGENTS_KEY = "All" 
     44        
     45    def __init__(self, engine, settings): 
    3546        """Initialize the instance. 
    3647        @param engine: A fife.Engine object 
    3748        @type emgome: fife.Engine  
     49        @param setting: The applications settigns 
     50        @type setting: fife_settings.Setting  
    3851        @return: None""" 
    39         # a World object (the fife stuff, essentially) 
    4052        self.map_change = False 
    4153        self.load_saver = False 
     
    4557        self.target_position = None 
    4658        self.target_map_name = None 
    47         self.target_map_file = None 
    4859        self.object_db = {} 
    49         # self.map is a Map object, set to none here 
    5060        self.active_map = None 
    5161        self.maps = {} 
    52         self.engine = engine         
     62        self.map_files = {} 
     63        self.agents = {} 
     64        self.agents[self.ALL_AGENTS_KEY] = {} 
     65        self.engine = engine 
     66        self.fife_model = engine.getModel() 
     67        self.maps_file = "maps/maps.yaml" 
     68        self.all_agents_file = "maps/all_agents.yaml" 
     69        self.object_db_file = "objects/ObjectDatabase.yaml" 
     70        self.agents_directory = "objects/" 
     71        self.dialogues_directory = "dialogue" 
     72        self.dialogues = {} 
     73        self.agent_import_files = {} 
     74        self.settings = settings 
    5375 
    5476    def checkAttributes(self, attributes): 
     
    7193        return attributes 
    7294     
     95    def createContainerObject(self, attributes): 
     96        """Create an object that can be stored in  
     97        an container and return it 
     98        @param attributes: Dictionary of all object attributes 
     99        @type attributes: Dictionary 
     100        @return: The created object 
     101        """ 
     102        # create the extra data 
     103        extra = {} 
     104        extra['controller'] = self 
     105        attributes = self.checkAttributes(attributes) 
     106         
     107        """TODO: Change when we use other and or more classes  
     108        for inventory objects""" 
     109        info = {} 
     110        info.update(attributes) 
     111        info.update(extra) 
     112        ID = info.pop("id") if info.has_key("id") else info.pop("ID") 
     113                 
     114        return CarryableItem(ID = ID, **info)   
     115       
    73116    def createInventoryObject(self, container, attributes): 
    74117        """Create an inventory object and place it into a container 
     
    78121           @param attributes: Dictionary of all object attributes 
    79122           @return: None""" 
    80         # create the extra data 
    81         extra = {} 
    82         extra['controller'] = self 
    83         attributes = self.checkAttributes(attributes) 
    84          
    85         """TODO: Change when we use other and or more classes  
    86         for inventory objects""" 
    87         from objects.composed import CarryableItem 
    88         info = {} 
    89         info.update(attributes) 
    90         info.update(extra) 
    91         ID = info.pop("id") 
    92          
    93         obj = CarryableItem(ID = ID, **info) 
     123        index = attributes.pop("index") if attributes.has_key("index") else None 
     124        slot = attributes.pop("slot") if attributes.has_key("slot") else None 
     125        obj = self.createContainerObject(attributes)         
    94126        #obj = createObject(attributes, extra) 
    95         container.placeItem(obj) 
     127        if slot: 
     128            container.moveItemToSlot(obj, slot) 
     129        else: 
     130            container.placeItem(obj, index) 
    96131         
    97132    def save(self, path, filename): 
     
    102137        fname = '/'.join([path, filename]) 
    103138        try: 
    104             save_file = open(fname, 'wb') 
     139            save_file = open(fname, 'w') 
    105140        except(IOError): 
    106             sys.stderr.write("Error: Can't find save game: " + fname + "\n") 
     141            sys.stderr.write("Error: Can't create save game: " + fname + "\n") 
    107142            return 
    108          
    109         # save the PC coordinates 
    110         coords = self.game_state.PlayerCharacter.behaviour.agent.getLocation().\ 
    111                     getMapCoordinates() 
    112         self.game_state.saved_pc_coordinates = (coords.x, coords.y) 
    113          
    114         # Pickle it  
    115         pickle.dump(self.game_state, save_file) 
     143        save_state = {} 
     144        save_state["Agents"] = {} 
     145        for map_name in self.agents: 
     146            if map_name == self.ALL_AGENTS_KEY: 
     147                continue 
     148            agents_dict = {} 
     149            for agent in self.agents[map_name]: 
     150                agent_obj = self.game_state.getObjectById(agent, map_name) 
     151                agent_inst = self.maps[map_name].agent_layer.getInstance(agent) 
     152                agent_dict = self.agents[map_name][agent] 
     153                agent_dict.update(agent_obj.getStateForSaving()) 
     154                agent_dict["Rotation"] = agent_inst.getRotation() 
     155                agents_dict[agent] = agent_dict 
     156            save_state["Agents"][map_name] = agents_dict 
     157        agents_dict = {} 
     158        for agent in self.agents["All"]: 
     159            map_name = self.agents["All"][agent]["Map"] 
     160            agent_dict = self.agents["All"][agent] 
     161            agent_obj = None 
     162            if agent == "PlayerCharacter": 
     163                agent_obj = self.game_state.PlayerCharacter 
     164            else: 
     165                agent_obj = self.game_state.getObjectById(agent, map_name) 
     166            if agent_obj: 
     167                agent_inst = self.maps[map_name].agent_layer.getInstance(agent) 
     168                agent_dict.update(agent_obj.getStateForSaving()) 
     169                agent_dict["Rotation"] = agent_inst.getRotation() 
     170                agent_dict["MapName"] = map_name 
     171            agents_dict[agent] = agent_dict 
     172        save_state["Agents"]["All"] = agents_dict 
     173        save_state["GameState"] = self.game_state.getStateForSaving() 
     174        yaml.dump(save_state, save_file) 
     175         
    116176        save_file.close()        
    117177 
     
    124184 
    125185        try: 
    126             load_file = open(fname, 'rb') 
     186            load_file = open(fname, 'r') 
    127187        except(IOError): 
    128188            sys.stderr.write("Error: Can't find save game file\n") 
    129189            return         
    130          
    131         self.game_state = pickle.load(load_file) 
     190        self.deleteMaps() 
     191        self.clearAgents() 
     192         
     193        save_state = yaml.load(load_file) 
     194        self.game_state.restoreFromState(save_state["GameState"]) 
     195        maps = save_state["Agents"] 
     196        for map_name in maps: 
     197            for agent_name in maps[map_name]: 
     198                agent = {agent_name:maps[map_name][agent_name]} 
     199                self.addAgent(map_name, agent) 
     200                 
    132201        load_file.close() 
    133  
    134         self.target_position = self.game_state.saved_pc_coordinates 
    135  
     202         
    136203        # Load the current map 
    137         if self.game_state.current_map_file: 
    138             self.loadMap(self.game_state.current_map_name, \ 
    139                          self.game_state.current_map_file)          
     204        if self.game_state.current_map_name: 
     205            self.loadMap(self.game_state.current_map_name)          
    140206 
    141207        # Recreate all the behaviours. These can't be saved because FIFE 
    142208        # objects cannot be pickled 
    143209         
    144         for map_id in self.game_state.objects: 
    145             for obj in self.game_state.objects[map_id].itervalues(): 
    146                 if obj.trueAttr("NPC") or obj.trueAttr("AnimatedContainer"): 
    147                     obj.createBehaviour(self.active_map.agent_layer) 
    148                     obj.setup() 
     210        self.placeAgents() 
     211        self.placePC() 
    149212       
    150213        # In most maps we'll create the PlayerCharacter Instance internally.  
    151214        # In these cases we need a target position 
    152215          
    153     def teleport(self, position): 
    154         """Called when a door is used that moves a player to a new 
    155            location on the same map. the setting of position may want 
    156            to be created as its own method down the road. 
    157            @type position: String Tuple 
    158            @param position: X,Y coordinates passed from engine.changeMap 
    159            @return: fife.Location""" 
     216    def teleport(self, agent, position): 
     217        """Called when a an agent is moved instantly to a new position.  
     218        The setting of position may wan to be created as its own method down the road. 
     219        @type position: String Tuple 
     220        @param position: X,Y coordinates passed from engine.changeMap 
     221        @return: fife.Location""" 
    160222        print position 
    161223        coord = fife.DoublePoint3D(float(position[0]), float(position[1]), 0) 
    162224        location = fife.Location(self.active_map.agent_layer) 
    163225        location.setMapCoordinates(coord) 
    164         self.game_state.PlayerCharacter.teleport(location) 
    165                  
     226        agent.teleport(location)          
     227                
    166228    def getObjectAtCoords(self, coords): 
    167229        """Get the object which is at the given coords 
    168             @type coords: fife.Screenpoint 
    169             @param coords: Coordinates where to check for an object 
    170             @rtype: fife.Object 
    171             @return: An object or None""" 
     230        @type coords: fife.Screenpoint 
     231        @param coords: Coordinates where to check for an object 
     232        @rtype: fife.Object 
     233        @return: An object or None""" 
    172234        instances = self.active_map.cameras[ 
    173235                                            self.active_map.my_cam_id].\ 
     
    215277        self.active_map.togglePause() 
    216278     
    217     def loadMap(self, map_name, map_file): 
     279    def readMapFiles(self): 
     280        """Read all a available map-files and store them""" 
     281        maps_data = file(self.maps_file) 
     282        self.map_files = yaml.load(maps_data)["Maps"] 
     283     
     284    def addAgent(self, namespace, agent): 
     285        """Adds an agent to the agents dictionary 
     286        @param namespace: the namespace where the agent is to be added to 
     287        @type namespace: str 
     288        @param agent: The agent to be added 
     289        @type agent: dict 
     290        """ 
     291        from local_loaders.loaders import loadImportFile 
     292        if not self.agents.has_key(namespace): 
     293            self.agents[namespace] = {} 
     294 
     295        self.agents[namespace].update(agent) 
     296        object_model = "" 
     297        agent_values = agent.values()[0] 
     298        if agent_values.has_key("ObjectModel"):  
     299            object_model =  agent_values["ObjectModel"] 
     300        else: 
     301            object_model = self.object_db[agent_values["ObjectType"]]["gfx"] 
     302        import_file = self.agent_import_files[object_model] 
     303        loadImportFile(import_file, self.engine) 
     304         
     305    def readAllAgents(self): 
     306        """Read the agents of the all_agents_file and store them""" 
     307        agents_data = file(self.all_agents_file) 
     308        agents = yaml.load_all(agents_data) 
     309        for agent in agents: 
     310            if not agent == None: 
     311                self.addAgent(self.ALL_AGENTS_KEY, agent)   
     312                 
     313    def getAgentsOfMap(self, map_name): 
     314        """Returns the agents that are on the given map 
     315        @param map_name: Name of the map 
     316        @type map_name: str 
     317        @return: A dictionary with the agents of the map 
     318        """ 
     319        if not self.agents.has_key(map_name): 
     320            return {} 
     321        ret_dict = self.agents[map_name].copy() 
     322        for agent_name, agent_value in self.agents[self.ALL_AGENTS_KEY].iteritems(): 
     323            if agent_value["Map"] == map_name: 
     324                ret_dict[agent_name] = agent_value 
     325        return ret_dict 
     326                 
     327    def getAgentsOfActiveMap(self): 
     328        """Returns the agents that are on active map 
     329        @return: A dictionary with the agents of the map 
     330        """ 
     331        return self.getAgentsOfMap(self.active_map.map.getId()) 
     332 
     333    def clearAgents(self): 
     334        """Resets the agents dictionary""" 
     335        self.agents = {} 
     336        self.agents[self.ALL_AGENTS_KEY] = {} 
     337     
     338    def loadMap(self, map_name): 
    218339        """Load a new map. 
    219340           @type map_name: string 
    220341           @param map_name: Name of the map to load 
    221            @type map_file: string 
    222            @param map_file: Filename of map file to load 
    223            @return: None""" 
    224         self.game_state.current_map_file = map_file 
     342           @return: None""" 
    225343        self.game_state.current_map_name = map_name 
    226344 
    227         if not map_name in self.maps:            
    228             new_map = Map(self.engine, self) 
     345        if not map_name in self.maps:   
     346            map_file = self.map_files[map_name] 
     347            map_agents_file = map_file.replace(".xml", "_agents.yaml")    
     348            new_map = GameMap(self.engine, self) 
    229349            self.maps[map_name] = new_map 
    230             new_map.load(map_file) 
     350            #Get the agents of the map 
     351            agents_data = file(map_agents_file) 
     352            agents = yaml.load_all(agents_data) 
     353            for agent in agents: 
     354                if not agent == None: 
     355                    self.addAgent(map_name, agent)   
     356            new_map.load(self.map_files[map_name]) 
    231357        else: 
    232358            self.setActiveMap(map_name) 
    233359 
     360    def createAgent(self, agent, inst_id): 
     361        object_type = agent["ObjectType"] 
     362        object_id = agent["ObjectModel"] \ 
     363                                if agent.has_key("ObjectModel") \ 
     364                                else None 
     365        if object_id == None: 
     366            object_id = self.object_db[object_type]["gfx"] 
     367        map_obj = self.fife_model.getObject(str(object_id), "PARPG") 
     368        if not map_obj: 
     369            print ''.join(['Object with inst_id=', str(object_id),  
     370                           ' ns=PARPG', \ 
     371                           ' could not be found. Omitting...']) 
     372 
     373        x_pos = agent["Position"][0] 
     374        y_pos = agent["Position"][1] 
     375        z_pos = agent["Position"][2] if len(agent["Position"]) == 3 else 0.0 
     376        stack_pos = agent["Stackposition"] if \ 
     377                        agent.has_key("StackPosition") \ 
     378                        else None 
     379        inst = self.active_map.agent_layer.\ 
     380                        createInstance(map_obj, 
     381                                       fife.ExactModelCoordinate(x_pos,  
     382                                                                 y_pos,  
     383                                                                 z_pos), 
     384                                       inst_id) 
     385 
     386        inst.setId(inst_id) 
     387        rotation = agent["Rotation"] 
     388        inst.setRotation(rotation) 
     389 
     390        fife.InstanceVisual.create(inst) 
     391        if (stack_pos): 
     392            inst.get2dGfxVisual().setStackPosition(int(stack_pos)) 
     393 
     394        if (map_obj.getAction('default')): 
     395            target = fife.Location(self.active_map.agent_layer) 
     396            inst.act('default', target, True) 
     397             
     398        inst_dict = {} 
     399        inst_dict["type"] = object_type 
     400        inst_dict["id"] = inst_id 
     401        inst_dict["xpos"] = x_pos 
     402        inst_dict["ypos"] = y_pos 
     403        inst_dict["gfx"] = object_id 
     404        inst_dict["is_open"] = parseBool(agent["Open"]) \ 
     405                                if agent.has_key("Open") \ 
     406                                else False 
     407        inst_dict["locked"] = parseBool(agent["Locked"]) \ 
     408                                if agent.has_key("Locked") \ 
     409                                else False 
     410        inst_dict["name"] = agent["ViewName"] 
     411        inst_dict["real_name"] = agent["RealName"] \ 
     412                                    if agent.has_key("RealName") \ 
     413                                    else agent["ViewName"] 
     414        inst_dict["text"] = agent["Text"] \ 
     415                                    if agent.has_key("Text") \ 
     416                                    else None 
     417        if self.dialogues.has_key(inst_id): 
     418            inst_dict["dialogue"] = self.dialogues[inst_id] 
     419        inst_dict["target_map_name"] = agent["TargetMap"] \ 
     420                                        if agent.\ 
     421                                            has_key("TargetMap") \ 
     422                                        else None 
     423        inst_dict["target_x"] = agent["TargetPosition"][0] \ 
     424                                    if agent.\ 
     425                                        has_key("TargetPosition") \ 
     426                                    else None 
     427        inst_dict["target_y"] = agent["TargetPosition"][1] \ 
     428                                    if agent.\ 
     429                                        has_key("TargetPosition") \ 
     430                                    else None 
     431        if agent.has_key("Inventory"): 
     432            inventory = Inventory() 
     433            inventory_objs = agent["Inventory"] 
     434            for inventory_obj in inventory_objs: 
     435                self.createInventoryObject(inventory, 
     436                                           inventory_obj  
     437                                           ) 
     438            inst_dict["inventory"] = inventory 
     439 
     440        if agent.has_key("Items"): 
     441            items = [] 
     442            inventory_objs = agent["Items"] 
     443            for inventory_obj in inventory_objs: 
     444                items.append(self.createContainerObject(inventory_obj)) 
     445            inst_dict["items"] = items 
     446 
     447                     
     448        self.createMapObject(self.active_map.agent_layer, inst_dict, inst) 
     449     
     450    def placeAgents(self): 
     451        """Places the current maps agents 
     452        """ 
     453        if not self.active_map: 
     454            return 
     455        agents = self.getAgentsOfMap(self.game_state.current_map_name) 
     456        for agent in agents: 
     457            if agent == "PlayerCharacter": 
     458                continue 
     459            if self.active_map.agent_layer.getInstances(agent): 
     460                continue 
     461            self.createAgent(agents[agent], agent) 
     462 
     463    def placePC(self): 
     464        """Places the PlayerCharacter on the map""" 
     465        agent = self.agents[self.ALL_AGENTS_KEY]["PlayerCharacter"] 
     466        inst_id = "PlayerCharacter" 
     467        self.createAgent(agent, inst_id) 
     468         
    234469        # create the PlayerCharacter agent 
    235470        self.active_map.addPC() 
    236471        self.game_state.PlayerCharacter.start() 
    237  
    238     def changeMap(self, map_name, map_file, target_position): 
     472                       
     473    def changeMap(self, map_name, target_position): 
    239474        """Registers for a map change on the next pump(). 
    240475           @type map_name: String 
     
    248483        if map_name != self.game_state.current_map_name: 
    249484            self.target_map_name = map_name 
    250             self.target_map_file = map_file 
    251485            self.target_position = target_position 
    252486            # issue the map change 
     
    262496        self.engine.getModel().deleteMaps() 
    263497        self.engine.getModel().deleteObjects() 
     498        self.game_state.clearObjects() 
    264499        self.maps = {} 
    265500         
     
    289524        if layer is not None: 
    290525            extra['agent_layer'] = layer 
    291         extra['controller'] = self 
    292526        attributes = self.checkAttributes(attributes) 
    293527         
     
    369603            self.game_state.PlayerCharacter.walk(position) 
    370604         
    371     def teleportPlayer(self, position): 
    372         """Code called when the player should teleport to another location 
     605    def teleportAgent(self, agent, position): 
     606        """Code called when an agent should teleport to another location 
    373607           @type position: fife.ScreenPoint 
    374608           @param position: Screen position to teleport to 
    375609           @return: None""" 
    376         self.game_state.PlayerCharacter.teleport(position) 
    377  
    378     def readObjectDB(self, db_file): 
     610        agent.teleport(position) 
     611        self.agents[agent.ID]["Position"] = position 
     612 
     613    def readObjectDB(self): 
    379614        """Reads the Object Information Database from a file. 
    380         @type db_file: String 
    381         @param db_file: The file to load from 
    382         """ 
    383         database_file = file(db_file, "r") 
     615        """ 
     616        database_file = file(self.object_db_file, "r") 
    384617        database = yaml.load_all(database_file) 
    385618        for object_info in database: 
    386619            self.object_db.update(object_info) 
     620 
     621    def getAgentImportFiles(self): 
     622        """Searches the agents directory for import files 
     623        """ 
     624        files = locateFiles("*.xml", self.agents_directory) 
     625        for xml_file in files: 
     626            xml_file = os.path.relpath(xml_file).replace("\\", "/") 
     627            root = ElementTree.parse(xml_file).getroot() 
     628            if root.tag == "object": 
     629                self.agent_import_files[root.attrib["id"]] = xml_file 
     630     
     631    def getDialogues(self): 
     632        """Searches the dialogue directory for dialogues 
     633        """ 
     634        files = locateFiles("*.yaml", self.dialogues_directory) 
     635        for dialogue_file in files: 
     636            dialogue_file = os.path.relpath(dialogue_file).replace("\\", "/") 
     637            dialogues = yaml.load_all(file(dialogue_file, "r")) 
     638            for dialogue in dialogues: 
     639                self.dialogues[dialogue["NPC"]] = dialogue 
Note: See TracChangeset for help on using the changeset viewer.