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

Revision 813, 31.7 KB checked in by aspidites, 9 years ago (diff)

Patch by Aspidites:

-updated all calls to settings.paths to the more readable settings.system_path and settings.user_path properties

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