source: branches/active/character_customization/game/parpg/gamemodel.py @ 794

Revision 794, 31.6 KB checked in by aspidites, 9 years ago (diff)

Patch by Aspidites

  • added "DataDirectory?" option to [fife] section of system.cfg
  • broke down *File options and made additonal *Directory options

where neccessary

  • updated references in source files to comply with these changes
  • Property svn:eol-style set to native
RevLine 
[54]1#   This file is part of PARPG.
2
3#   PARPG is free software: you can redistribute it and/or modify
4#   it under the terms of the GNU General Public License as published by
5#   the Free Software Foundation, either version 3 of the License, or
6#   (at your option) any later version.
7
8#   PARPG is distributed in the hope that it will be useful,
9#   but WITHOUT ANY WARRANTY; without even the implied warranty of
10#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11#   GNU General Public License for more details.
12
13#   You should have received a copy of the GNU General Public License
14#   along with PARPG.  If not, see <http://www.gnu.org/licenses/>.
15
16# there should be NO references to FIFE here!
[312]17import sys
[563]18import os.path
[668]19import logging
[610]20from copy import deepcopy
21
22from fife import fife
[658]23from fife.extensions.serializers.xmlobject import XMLObjectLoader
[610]24
[177]25from gamestate import GameState
[550]26from objects import createObject
[610]27from objects.composed import CarryableItem, CarryableContainer
[563]28from gamemap import GameMap
29from common.utils import locateFiles
30from common.utils import parseBool
31from inventory import Inventory
[736]32from parpg.dialogueparsers import YamlDialogueParser, DialogueFormatError
[570]33
[563]34try:
35    import xml.etree.cElementTree as ElementTree
36except ImportError:
37    import xml.etree.ElementTree as ElementTree
[552]38
[537]39import yaml
[54]40
[548]41class GameModel(object):
42    """GameModel holds the logic for the game.
[54]43       Since some data (object position and so forth) is held in the
44       fife, and would be pointless to replicate, we hold a instance of
45       the fife view here. This also prevents us from just having a
[142]46       function heavy controller."""
[563]47    ALL_AGENTS_KEY = "All"
[565]48    MAX_ID_NUMBER = 1000
49   
[563]50    def __init__(self, engine, settings):
[314]51        """Initialize the instance.
[552]52        @param engine: A fife.Engine object
53        @type emgome: fife.Engine
[563]54        @param setting: The applications settigns
[756]55        @type setting: parpg.settings.Settings object
[552]56        @return: None"""
[794]57        self.settings = settings
58        data_dir = self.settings.fife.DataDirectory
59
[312]60        self.map_change = False
[323]61        self.load_saver = False
62        self.savegame = None
[794]63        quests_directory = os.path.join(data_dir,
64                                        self.settings.parpg.QuestsDirectory)
65        self.game_state = GameState(quests_dir=quests_directory)
[574]66        #self.game_state.quest_engine =
67        #self.game_state.quest_engine.readQuests()
[295]68        self.pc_run = 1
[312]69        self.target_position = None
[314]70        self.target_map_name = None
[537]71        self.object_db = {}
[552]72        self.active_map = None
[563]73        self.map_files = {}
74        self.agents = {}
75        self.agents[self.ALL_AGENTS_KEY] = {}
76        self.engine = engine
77        self.fife_model = engine.getModel()
[756]78
79        # set values from settings
[794]80        maps_file = os.path.join(data_dir, self.settings.parpg.MapsDirectory,
81                                 self.settings.parpg.MapsFile)
82        self.game_state.maps_file = maps_file
83        all_agents_file = os.path.join(data_dir, 
84                                       self.settings.parpg.MapsDirectory,
85                                       self.settings.parpg.AllAgentsFile)
86        self.all_agents_file = all_agents_file
87        objects_dir = os.path.join(data_dir,
88                                    self.settings.parpg.ObjectsDirectory)
89        self.objects_directory = objects_dir
90        object_db_file = os.path.join(self.objects_directory,
91                                      self.settings.parpg.ObjectDatabaseFile)
92        self.object_db_file = object_db_file
93        dialogues_dir = os.path.join(data_dir, 
94                                     self.settings.parpg.DialoguesDirectory)
95        self.dialogues_directory = dialogues_dir
[563]96        self.dialogues = {}
97        self.agent_import_files = {}
[658]98        self.obj_loader = XMLObjectLoader(
99                                          self.engine.getImagePool(), 
100                                          self.engine.getAnimationPool(), 
101                                          self.engine.getModel(),
102                                          self.engine.getVFS() 
103                                          )
[128]104
[552]105    def checkAttributes(self, attributes):
106        """Checks for attributes that where not given in the map file
107        and fills them with values from the object database
108        @param attributes: attributes to check
109        @type attributes: Dictionary
[571]110        @return: The modified attributes""" 
[552]111        if attributes.has_key("object_type"):
112            class_name = attributes.pop("object_type")
113        else:
114            class_name = attributes["type"]
[596]115        if not attributes.has_key("type"):
116            attributes["type"] = class_name
[552]117        if self.object_db.has_key(class_name):
[571]118            db_attributes = deepcopy(self.object_db[class_name])
[552]119            for key in db_attributes.keys():
120                if attributes.has_key(key):
121                    attributes[key] = attributes[key] or db_attributes[key]
122                else:
123                    attributes[key] = db_attributes[key]
124        return attributes
125   
[595]126    def isIDUsed(self, ID):
127        if self.game_state.hasObject(ID):
128            return True
129        for namespace in self.agents:
130            if ID in self.agents[namespace]:
131                return True
132        return False
133   
134    def createUniqueID(self, ID):
135        if self.isIDUsed(ID):
136            id_number = 1
137            while self.isIDUsed(ID + "_" + str(id_number)):
138                id_number += 1
139                if id_number > self.MAX_ID_NUMBER:
140                    raise ValueError(
141                        "Number exceeds MAX_ID_NUMBER:" + str(self.MAX_ID_NUMBER))
142           
143            ID = ID + "_" + str(id_number)
144        return ID
145
[610]146    def createContainerItems(self, container_objs):
147        """Create the items of a container from a dictionary
148        @param container_objs: Dictionary containing the items
149        @type container_objs: dict"""
150        items = []
151        for container_obj in container_objs:
152            items.append(self.createContainerObject(container_obj))
153       
154        return items
155
[563]156    def createContainerObject(self, attributes):
157        """Create an object that can be stored in
158        an container and return it
159        @param attributes: Dictionary of all object attributes
160        @type attributes: Dictionary
[579]161        @return: The created object """
[552]162        # create the extra data
163        extra = {}
164        extra['controller'] = self
165        attributes = self.checkAttributes(attributes)
166       
167        info = {}
168        info.update(attributes)
169        info.update(extra)
[563]170        ID = info.pop("id") if info.has_key("id") else info.pop("ID")
[609]171        if not info.has_key("item_type"):
172            info["item_type"] = info["type"]
[595]173        ID = self.createUniqueID(ID)
[610]174        if info.has_key("attributes"):
175            attributes = info["attributes"]
176            if "Container" in attributes:
177                info["actions"]["Open"] = ""
178                if info.has_key("Items"):
179                    inventory_objs = info["Items"]
180                    info["items"] = self.createContainerItems(inventory_objs)
181               
182                new_item = CarryableContainer(ID = ID, **info) 
[615]183            else:
184                new_item = CarryableItem(ID = ID, **info) 
[610]185        else:
186            new_item = CarryableItem(ID = ID, **info) 
[565]187        self.game_state.addObject(None, new_item)
188        return new_item
[563]189     
190    def createInventoryObject(self, container, attributes):
191        """Create an inventory object and place it into a container
192           @type container: base.Container
193           @param container: Container where the item is on
194           @type attributes: Dictionary
195           @param attributes: Dictionary of all object attributes
196           @return: None"""
197        index = attributes.pop("index") if attributes.has_key("index") else None
198        slot = attributes.pop("slot") if attributes.has_key("slot") else None
199        obj = self.createContainerObject(attributes)       
[552]200        #obj = createObject(attributes, extra)
[563]201        if slot:
202            container.moveItemToSlot(obj, slot)
203        else:
204            container.placeItem(obj, index)
[571]205   
206    def deleteObject(self, object_id):
207        """Removes an object from the game
208        @param object_id: ID of the object
[579]209        @type object_id: str """
[595]210        del self.agents["All"][object_id]
[571]211        self.game_state.deleteObject(object_id)
[552]212       
[162]213    def save(self, path, filename):
[150]214        """Writes the saver to a file.
215           @type filename: string
216           @param filename: the name of the file to write to
217           @return: None"""
[341]218        fname = '/'.join([path, filename])
[151]219        try:
[563]220            save_file = open(fname, 'w')
[151]221        except(IOError):
[563]222            sys.stderr.write("Error: Can't create save game: " + fname + "\n")
[151]223            return
[563]224        save_state = {}
225        save_state["Agents"] = {}
226        for map_name in self.agents:
227            if map_name == self.ALL_AGENTS_KEY:
228                continue
229            agents_dict = {}
230            for agent in self.agents[map_name]:
231                agent_obj = self.game_state.getObjectById(agent, map_name)
[579]232                agent_inst = self.game_state.maps[map_name].\
233                                    agent_layer.getInstance(agent)
[563]234                agent_dict = self.agents[map_name][agent]
235                agent_dict.update(agent_obj.getStateForSaving())
236                agent_dict["Rotation"] = agent_inst.getRotation()
237                agents_dict[agent] = agent_dict
238            save_state["Agents"][map_name] = agents_dict
239        agents_dict = {}
240        for agent in self.agents["All"]:
241            map_name = self.agents["All"][agent]["Map"]
242            agent_dict = self.agents["All"][agent]
243            agent_obj = None
244            if agent == "PlayerCharacter":
[579]245                agent_obj = self.game_state.player_character
[563]246            else:
247                agent_obj = self.game_state.getObjectById(agent, map_name)
248            if agent_obj:
[579]249                agent_inst = self.game_state.maps[map_name].\
250                                    agent_layer.getInstance(agent)
[563]251                agent_dict.update(agent_obj.getStateForSaving())
252                agent_dict["Rotation"] = agent_inst.getRotation()
253                agent_dict["MapName"] = map_name
254            agents_dict[agent] = agent_dict
255        save_state["Agents"]["All"] = agents_dict
256        save_state["GameState"] = self.game_state.getStateForSaving()
257        yaml.dump(save_state, save_file)
[198]258       
[552]259        save_file.close()       
[148]260
[356]261    def load(self, path, filename):
[150]262        """Loads a saver from a file.
263           @type filename: string
[323]264           @param filename: the name of the file (including path) to load from
[150]265           @return: None"""
[356]266        fname = '/'.join([path, filename])
267
[151]268        try:
[563]269            load_file = open(fname, 'r')
[151]270        except(IOError):
271            sys.stderr.write("Error: Can't find save game file\n")
[552]272            return       
[563]273        self.deleteMaps()
274        self.clearAgents()
[356]275       
[563]276        save_state = yaml.load(load_file)
277        self.game_state.restoreFromState(save_state["GameState"])
278        maps = save_state["Agents"]
279        for map_name in maps:
280            for agent_name in maps[map_name]:
281                agent = {agent_name:maps[map_name][agent_name]}
282                self.addAgent(map_name, agent)
283               
[498]284        # Load the current map
[563]285        if self.game_state.current_map_name:
286            self.loadMap(self.game_state.current_map_name)         
[566]287        load_file.close()
288       
[498]289
[356]290        # Recreate all the behaviours. These can't be saved because FIFE
291        # objects cannot be pickled
[498]292       
[563]293        self.placeAgents()
294        self.placePC()
[498]295     
[552]296        # In most maps we'll create the PlayerCharacter Instance internally.
297        # In these cases we need a target position
298         
[563]299    def teleport(self, agent, position):
300        """Called when a an agent is moved instantly to a new position.
301        The setting of position may wan to be created as its own method down the road.
302        @type position: String Tuple
303        @param position: X,Y coordinates passed from engine.changeMap
304        @return: fife.Location"""
[552]305        print position
306        coord = fife.DoublePoint3D(float(position[0]), float(position[1]), 0)
307        location = fife.Location(self.active_map.agent_layer)
308        location.setMapCoordinates(coord)
[563]309        agent.teleport(location)         
310               
[552]311    def getObjectAtCoords(self, coords):
312        """Get the object which is at the given coords
[563]313        @type coords: fife.Screenpoint
314        @param coords: Coordinates where to check for an object
315        @rtype: fife.Object
316        @return: An object or None"""
[552]317        instances = self.active_map.cameras[
318                                            self.active_map.my_cam_id].\
319            getMatchingInstances(coords, self.active_map.agent_layer)
320        # no object returns an empty tuple
321        if(instances != ()):
322            front_y = 0
323           
[540]324
[552]325            for obj in instances:
326                # check to see if this in our list at all
327                if(self.objectActive(obj.getId())):
328                    # check if the object is on the foreground
329                    obj_map_coords = \
330                                      obj.getLocation().getMapCoordinates()
331                    obj_screen_coords = self.active_map.\
332                        cameras[self.active_map.my_cam_id]\
333                        .toScreenCoordinates(obj_map_coords)
334
335                    if obj_screen_coords.y > front_y:
336                        #Object on the foreground
337                        front_y = obj_screen_coords.y
338                        return obj
339                    else:
340                        return None
[540]341        else:
[552]342            return None
343
344    def getCoords(self, click):
345        """Get the map location x, y coordinates from the screen coordinates
346           @type click: fife.ScreenPoint
347           @param click: Screen coordinates
348           @rtype: fife.Location
349           @return: The map coordinates"""
350        coord = self.active_map.cameras[self.active_map.my_cam_id].\
351                    toMapCoordinates(click, False)
352        coord.z = 0
353        location = fife.Location(self.active_map.agent_layer)
354        location.setMapCoordinates(coord)
355        return location
356
[632]357    def pause(self, paused):
358        """ Pause/Unpause the game
359        @return: nothing"""
[648]360        if self.active_map:
361            self.active_map.pause(paused)
[632]362   
[552]363    def togglePause(self):
[632]364        """ Toggle paused state.
365        @return: nothing"""
[552]366        self.active_map.togglePause()
[632]367       
368    def isPaused(self):
369        """Returns wheter the game is paused or not"""
370        return self.active_map.isPaused()
[540]371   
[563]372    def readMapFiles(self):
373        """Read all a available map-files and store them"""
[571]374        maps_data = file(self.game_state.maps_file)
[563]375        self.map_files = yaml.load(maps_data)["Maps"]
376   
377    def addAgent(self, namespace, agent):
378        """Adds an agent to the agents dictionary
379        @param namespace: the namespace where the agent is to be added to
380        @type namespace: str
381        @param agent: The agent to be added
[579]382        @type agent: dict """
[658]383        from fife.extensions.serializers.xml_loader_tools import loadImportFile
[563]384        if not self.agents.has_key(namespace):
385            self.agents[namespace] = {}
[566]386           
[595]387        agent_values = agent.values()[0]
388        unique_agent_id = self.createUniqueID(agent.keys()[0])
389        del agent[agent.keys()[0]]
390        agent[unique_agent_id] = agent_values
[563]391        self.agents[namespace].update(agent)
392        object_model = ""
393        if agent_values.has_key("ObjectModel"): 
394            object_model =  agent_values["ObjectModel"]
[592]395        elif agent_values["ObjectType"] == "MapItem":
[596]396            object_data = self.object_db[agent_values["ItemType"]]
397            object_model = object_data["gfx"] if object_data.has_key("gfx") \
398                        else "generic_item"
[563]399        else:
400            object_model = self.object_db[agent_values["ObjectType"]]["gfx"]
401        import_file = self.agent_import_files[object_model]
[658]402        loadImportFile(self.obj_loader, import_file, self.engine)
[563]403       
[566]404    def readAgentsOfMap(self, map_name):
405        """Read the agents of the map
406        @param map_name: Name of the map
[579]407        @type map_name: str """
[566]408        #Get the agents of the map       
409        map_agents_file = self.map_files[map_name].\
410                            replace(".xml", "_agents.yaml")   
411        agents_data = file(map_agents_file)
412        agents = yaml.load_all(agents_data)
413        for agent in agents:
414            if not agent == None:
415                self.addAgent(map_name, agent) 
416   
[563]417    def readAllAgents(self):
418        """Read the agents of the all_agents_file and store them"""
419        agents_data = file(self.all_agents_file)
420        agents = yaml.load_all(agents_data)
421        for agent in agents:
422            if not agent == None:
423                self.addAgent(self.ALL_AGENTS_KEY, agent) 
424               
425    def getAgentsOfMap(self, map_name):
426        """Returns the agents that are on the given map
427        @param map_name: Name of the map
428        @type map_name: str
[579]429        @return: A dictionary with the agents of the map"""
[563]430        if not self.agents.has_key(map_name):
431            return {}
432        ret_dict = self.agents[map_name].copy()
[579]433        for agent_name, agent_value in self.agents[self.ALL_AGENTS_KEY]\
434                                                .iteritems():
[563]435            if agent_value["Map"] == map_name:
436                ret_dict[agent_name] = agent_value
437        return ret_dict
438               
439    def getAgentsOfActiveMap(self):
440        """Returns the agents that are on active map
[579]441        @return: A dictionary with the agents of the map """
[563]442        return self.getAgentsOfMap(self.active_map.map.getId())
443
444    def clearAgents(self):
445        """Resets the agents dictionary"""
446        self.agents = {}
447        self.agents[self.ALL_AGENTS_KEY] = {}
448   
449    def loadMap(self, map_name):
[552]450        """Load a new map.
451           @type map_name: string
452           @param map_name: Name of the map to load
[540]453           @return: None"""
[571]454        if not map_name in self.game_state.maps: 
[563]455            map_file = self.map_files[map_name]
456            new_map = GameMap(self.engine, self)
[571]457            self.game_state.maps[map_name] = new_map
[610]458            new_map.load(map_file)   
459
[563]460    def createAgent(self, agent, inst_id):
461        object_type = agent["ObjectType"]
462        object_id = agent["ObjectModel"] \
463                                if agent.has_key("ObjectModel") \
464                                else None
465        if object_id == None:
[592]466            if object_type == "MapItem":
[596]467                object_data = self.object_db[agent["ItemType"]]
468                object_id = object_data["gfx"] if object_data.has_key("gfx") \
469                            else "generic_item"
[592]470            else:
471                object_id = self.object_db[object_type]["gfx"]
[563]472        map_obj = self.fife_model.getObject(str(object_id), "PARPG")
473        if not map_obj:
474            print ''.join(['Object with inst_id=', str(object_id), 
475                           ' ns=PARPG', \
476                           ' could not be found. Omitting...'])
477
478        x_pos = agent["Position"][0]
479        y_pos = agent["Position"][1]
[594]480        z_pos = agent["Position"][2] if len(agent["Position"]) == 3 \
481                                        else -0.1 if object_type == "MapItem" \
482                                        else 0.0 
[563]483        stack_pos = agent["Stackposition"] if \
484                        agent.has_key("StackPosition") \
485                        else None
486        inst = self.active_map.agent_layer.\
487                        createInstance(map_obj,
488                                       fife.ExactModelCoordinate(x_pos, 
489                                                                 y_pos, 
490                                                                 z_pos),
491                                       inst_id)
[595]492        inst.setId(inst_id)
[563]493
494        rotation = agent["Rotation"]
495        inst.setRotation(rotation)
496
497        fife.InstanceVisual.create(inst)
498        if (stack_pos):
499            inst.get2dGfxVisual().setStackPosition(int(stack_pos))
500
501        if (map_obj.getAction('default')):
502            target = fife.Location(self.active_map.agent_layer)
503            inst.act('default', target, True)
504           
505        inst_dict = {}
[595]506        inst_dict["id"] = inst_id
[563]507        inst_dict["type"] = object_type
508        inst_dict["xpos"] = x_pos
509        inst_dict["ypos"] = y_pos
510        inst_dict["gfx"] = object_id
511        inst_dict["is_open"] = parseBool(agent["Open"]) \
512                                if agent.has_key("Open") \
513                                else False
514        inst_dict["locked"] = parseBool(agent["Locked"]) \
515                                if agent.has_key("Locked") \
516                                else False
517        inst_dict["name"] = agent["ViewName"]
518        inst_dict["real_name"] = agent["RealName"] \
519                                    if agent.has_key("RealName") \
520                                    else agent["ViewName"]
521        inst_dict["text"] = agent["Text"] \
522                                    if agent.has_key("Text") \
523                                    else None
524        if self.dialogues.has_key(inst_id):
525            inst_dict["dialogue"] = self.dialogues[inst_id]
526        inst_dict["target_map_name"] = agent["TargetMap"] \
527                                        if agent.\
528                                            has_key("TargetMap") \
529                                        else None
530        inst_dict["target_x"] = agent["TargetPosition"][0] \
531                                    if agent.\
532                                        has_key("TargetPosition") \
533                                    else None
534        inst_dict["target_y"] = agent["TargetPosition"][1] \
535                                    if agent.\
536                                        has_key("TargetPosition") \
537                                    else None
538        if agent.has_key("Inventory"):
539            inventory = Inventory()
540            inventory_objs = agent["Inventory"]
541            for inventory_obj in inventory_objs:
542                self.createInventoryObject(inventory,
543                                           inventory_obj
544                                           )
545            inst_dict["inventory"] = inventory
546
547        if agent.has_key("Items"):
[610]548            container_objs = agent["Items"]
549            items = self.createContainerItems(container_objs)
[563]550            inst_dict["items"] = items
[592]551           
552        if agent.has_key("ItemType"):
[596]553            if not agent.has_key("item"):
554                item_data = {}
555                item_data["type"] = agent["ItemType"]
556                item_data["ID"] = inst_id
[608]557                item_data = self.createContainerObject(item_data)
[596]558            else:
559                item_data = agent["item"]
[595]560            inst_dict["item"] = item_data
[609]561            inst_dict["item_type"] = agent["ItemType"]
[595]562
[667]563        self.createMapObject(self.active_map.agent_layer, inst_dict)
[563]564   
565    def placeAgents(self):
[579]566        """Places the current maps agents """
[563]567        if not self.active_map:
568            return
569        agents = self.getAgentsOfMap(self.game_state.current_map_name)
570        for agent in agents:
571            if agent == "PlayerCharacter":
572                continue
573            if self.active_map.agent_layer.getInstances(agent):
574                continue
575            self.createAgent(agents[agent], agent)
576
577    def placePC(self):
578        """Places the PlayerCharacter on the map"""
579        agent = self.agents[self.ALL_AGENTS_KEY]["PlayerCharacter"]
580        inst_id = "PlayerCharacter"
581        self.createAgent(agent, inst_id)
582       
[552]583        # create the PlayerCharacter agent
584        self.active_map.addPC()
[579]585        self.game_state.player_character.start()
[574]586        if agent.has_key("PeopleKnown"):
[590]587            self.game_state.player_character.people_i_know = agent["PeopleKnown"]
[563]588                     
[566]589    def changeMap(self, map_name, target_position = None):
[552]590        """Registers for a map change on the next pump().
591           @type map_name: String
592           @param map_name: Id of the map to teleport to
593           @type map_file: String
594           @param map_file: Filename of the map to teleport to
595           @type target_position: Tuple
596           @param target_position: Position of PlayerCharacter on target map.
597           @return None"""
598        # set the parameters for the map change if moving to a new map
599        if map_name != self.game_state.current_map_name:
600            self.target_map_name = map_name
601            self.target_position = target_position
602            # issue the map change
603            self.map_change = True
604
605    def deleteMaps(self):
606        """Clear all currently loaded maps from FIFE as well as clear our
607            local map cache
608            @return: nothing"""
609        self.engine.getModel().deleteMaps()
610        self.engine.getModel().deleteObjects()
[563]611        self.game_state.clearObjects()
[571]612        self.game_state.maps = {}
[540]613       
[552]614    def setActiveMap(self, map_name):
615        """Sets the active map that is to be rendered.
616           @type map_name: String
617           @param map_name: The name of the map to load
618           @return: None"""
619        # Turn off the camera on the old map before we turn on the camera
620        # on the new map.
621        self.active_map.cameras[self.active_map.my_cam_id].setEnabled(False)
622        # Make the new map active.
[571]623        self.active_map = self.game_state.maps[map_name]
[552]624        self.active_map.makeActive()
[566]625        self.game_state.current_map_name = map_name
[552]626
[667]627    def createMapObject (self, layer, attributes):
[264]628        """Create an object and add it to the current map.
[310]629           @type layer: fife.Layer
630           @param layer: FIFE layer object exists in
631           @type attributes: Dictionary
632           @param attributes: Dictionary of all object attributes
633           @type instance: fife.Instance
634           @param instance: FIFE instance corresponding to the object
[476]635           @return: None"""
[198]636        # create the extra data
637        extra = {}
[540]638        if layer is not None:
639            extra['agent_layer'] = layer
640        attributes = self.checkAttributes(attributes)
[198]641       
[264]642        obj = createObject(attributes, extra)
643       
644        if obj.trueAttr("PC"):
[667]645            self.addPC(layer, obj)
[264]646        else:
[667]647            self.addObject(layer, obj) 
[178]648
[667]649    def addPC(self, layer, player_char):
[552]650        """Add the PlayerCharacter to the map
[310]651           @type layer: fife.Layer
652           @param layer: FIFE layer object exists in
[552]653           @type player_char: PlayerCharacter
654           @param player_char: PlayerCharacter object
[310]655           @type instance: fife.Instance
[552]656           @param instance: FIFE instance of PlayerCharacter
[476]657           @return: None"""
[552]658        # For now we copy the PlayerCharacter,
659        # in the future we will need to copy
660        # PlayerCharacter specifics between the different PlayerCharacter's
[579]661        self.game_state.player_character = player_char
662        self.game_state.player_character.setup()       
[770]663        self.game_state.player_character.behaviour.speed = self.settings.parpg.PCSpeed
[62]664
[770]665
[667]666    def addObject(self, layer, obj):
[264]667        """Adds an object to the map.
[310]668           @type layer: fife.Layer
669           @param layer: FIFE layer object exists in
670           @type obj: GameObject
671           @param obj: corresponding object class
672           @type instance: fife.Instance
673           @param instance: FIFE instance of object
[476]674           @return: None"""
[314]675        ref = self.game_state.getObjectById(obj.ID, \
676                                            self.game_state.current_map_name) 
[198]677        if ref is None:
678            # no, add it to the game state
[565]679            self.game_state.addObject(self.game_state.current_map_name, obj)
[198]680        else:
681            # yes, use the current game state data
682            obj.X = ref.X
683            obj.Y = ref.Y
684            obj.gfx = ref.gfx 
[323]685             
[198]686        if obj.trueAttr("NPC"):
[150]687            # create the agent
[198]688            obj.setup()
[770]689            obj.behaviour.speed = self.settings.parpg.PCSpeed - 1
[552]690            # create the PlayerCharacter agent
[198]691            obj.start()
[478]692        if obj.trueAttr("AnimatedContainer"):
693            # create the agent
694            obj.setup()
[58]695
[104]696    def objectActive(self, ident):
697        """Given the objects ID, pass back the object if it is active,
[142]698           False if it doesn't exist or not displayed
699           @type ident: string
700           @param ident: ID of object
701           @rtype: boolean
702           @return: Status of result (True/False)"""
[579]703        for game_object in \
[341]704           self.game_state.getObjectsFromMap(self.game_state.current_map_name):
[579]705            if (game_object.ID == ident):
[104]706                # we found a match
[579]707                return game_object
[104]708        # no match
[552]709        return False   
[104]710
[552]711    def movePlayer(self, position):
712        """Code called when the player should move to another location
[142]713           @type position: fife.ScreenPoint
[552]714           @param position: Screen position to move to
[142]715           @return: None"""
[312]716        if(self.pc_run == 1):
[579]717            self.game_state.player_character.run(position)
[295]718        else:
[579]719            self.game_state.player_character.walk(position)
[323]720       
[563]721    def teleportAgent(self, agent, position):
722        """Code called when an agent should teleport to another location
[552]723           @type position: fife.ScreenPoint
724           @param position: Screen position to teleport to
725           @return: None"""
[563]726        agent.teleport(position)
727        self.agents[agent.ID]["Position"] = position
[150]728
[563]729    def readObjectDB(self):
[579]730        """Reads the Object Information Database from a file. """
[563]731        database_file = file(self.object_db_file, "r")
[537]732        database = yaml.load_all(database_file)
733        for object_info in database:
734            self.object_db.update(object_info)
[563]735
736    def getAgentImportFiles(self):
[579]737        """Searches the agents directory for import files """
[794]738        files = locateFiles("*.xml", self.objects_directory)
[563]739        for xml_file in files:
740            xml_file = os.path.relpath(xml_file).replace("\\", "/")
[636]741            try:
742                root = ElementTree.parse(xml_file).getroot()
743                if root.tag == "object":
744                    self.agent_import_files[root.attrib["id"]] = xml_file
745            except SyntaxError as error:
746                assert(isinstance(error, SyntaxError))
747                print "Error parsing file " + xml_file + ": " + error.msg
748                #TODO: We may want to make this an fatal error later.
[563]749   
750    def getDialogues(self):
[579]751        """Searches the dialogue directory for dialogues """
[563]752        files = locateFiles("*.yaml", self.dialogues_directory)
[668]753        dialogue_parser = YamlDialogueParser()
754        for dialogue_filepath in files:
755            dialogue_filepath = os.path.relpath(dialogue_filepath) \
756                                .replace("\\", "/")
757            # Note Technomage 2010-11-13: the new DialogueEngine uses its own
758            #     parser now, YamlDialogueParser.
759#            dialogues = yaml.load_all(file(dialogue_file, "r"))
760            with file(dialogue_filepath, 'r') as dialogue_file:
761                try:
762                    dialogue = dialogue_parser.load(dialogue_file)
[685]763                except (DialogueFormatError,) as error:
[668]764                    logging.error('unable to load dialogue file {0}: {1}'
765                                  .format(dialogue_filepath, error))
766                else:
767                    self.dialogues[dialogue.npc_name] = dialogue
768            # Note Technomage 2010-11-13: the below code is used to load
769            #     multiple dialogues from a single file. Is this functionality
770            #     used/necessary?
771#            for dialogue in dialogues:
772#                self.dialogues[dialogue["NPC"]] = dialogue
Note: See TracBrowser for help on using the repository browser.