comparison src/parpg/gamemodel.py @ 0:1fd2201f5c36

Initial commit of parpg-core.
author M. George Hansen <technopolitica@gmail.com>
date Sat, 14 May 2011 01:12:35 -0700
parents
children d60f1dab8469
comparison
equal deleted inserted replaced
-1:000000000000 0:1fd2201f5c36
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!
17 import sys
18 import os.path
19 import logging
20 from copy import deepcopy
21
22 from fife import fife
23 from fife.extensions.serializers.xmlobject import XMLObjectLoader
24
25 from gamestate import GameState
26 from objects import createObject
27 from objects.composed import CarryableItem, CarryableContainer
28 from gamemap import GameMap
29 from common.utils import locateFiles
30 from common.utils import parseBool
31 from inventory import Inventory
32 from parpg.dialogueparsers import YamlDialogueParser, DialogueFormatError
33
34 try:
35 import xml.etree.cElementTree as ElementTree
36 except ImportError:
37 import xml.etree.ElementTree as ElementTree
38
39 import yaml
40
41 logger = logging.getLogger('gamemodel')
42
43 class GameModel(object):
44 """GameModel holds the logic for the game.
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
48 function heavy controller."""
49 ALL_AGENTS_KEY = "All"
50 MAX_ID_NUMBER = 1000
51
52 def __init__(self, engine, settings):
53 """Initialize the instance.
54 @param engine: A fife.Engine object
55 @type emgome: fife.Engine
56 @param setting: The applications settigns
57 @type setting: parpg.settings.Settings object
58 @return: None"""
59 self.settings = settings
60
61 self.map_change = False
62 self.load_saver = False
63 self.savegame = None
64 quests_directory = os.path.join(self.settings.system_path,
65 self.settings.parpg.QuestsPath)
66 self.game_state = GameState(quests_dir=quests_directory)
67 #self.game_state.quest_engine =
68 #self.game_state.quest_engine.readQuests()
69 self.pc_run = 1
70 self.target_position = None
71 self.target_map_name = None
72 self.object_db = {}
73 self.active_map = None
74 self.map_files = {}
75 self.agents = {}
76 self.agents[self.ALL_AGENTS_KEY] = {}
77 self.engine = engine
78 self.fife_model = engine.getModel()
79
80 # set values from settings
81 maps_file = os.path.join(self.settings.system_path,
82 self.settings.parpg.MapsPath,
83 self.settings.parpg.MapsFile)
84 self.game_state.maps_file = maps_file
85 all_agents_file = os.path.join(self.settings.system_path,
86 self.settings.parpg.MapsPath,
87 self.settings.parpg.AllAgentsFile)
88 self.all_agents_file = all_agents_file
89 objects_dir = os.path.join(self.settings.system_path,
90 self.settings.parpg.ObjectsPath)
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
95 dialogues_dir = os.path.join(self.settings.system_path,
96 self.settings.parpg.DialoguesPath)
97 self.dialogues_directory = dialogues_dir
98 self.dialogues = {}
99 self.agent_import_files = {}
100 self.obj_loader = XMLObjectLoader(
101 self.engine.getImagePool(),
102 self.engine.getAnimationPool(),
103 self.engine.getModel(),
104 self.engine.getVFS()
105 )
106
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
112 @return: The modified attributes"""
113 if attributes.has_key("object_type"):
114 class_name = attributes.pop("object_type")
115 else:
116 class_name = attributes["type"]
117 if not attributes.has_key("type"):
118 attributes["type"] = class_name
119 if self.object_db.has_key(class_name):
120 db_attributes = deepcopy(self.object_db[class_name])
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
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
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
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
163 @return: The created object """
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)
172 ID = info.pop("id") if info.has_key("id") else info.pop("ID")
173 if not info.has_key("item_type"):
174 info["item_type"] = info["type"]
175 ID = self.createUniqueID(ID)
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)
185 else:
186 new_item = CarryableItem(ID = ID, **info)
187 else:
188 new_item = CarryableItem(ID = ID, **info)
189 self.game_state.addObject(None, new_item)
190 return new_item
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)
202 #obj = createObject(attributes, extra)
203 if slot:
204 container.moveItemToSlot(obj, slot)
205 else:
206 container.placeItem(obj, index)
207
208 def deleteObject(self, object_id):
209 """Removes an object from the game
210 @param object_id: ID of the object
211 @type object_id: str """
212 del self.agents["All"][object_id]
213 self.game_state.deleteObject(object_id)
214
215 def save(self, path, filename):
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"""
220 fname = '/'.join([path, filename])
221 try:
222 save_file = open(fname, 'w')
223 except(IOError):
224 sys.stderr.write("Error: Can't create save game: " + fname + "\n")
225 return
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)
234 agent_inst = self.game_state.maps[map_name].\
235 agent_layer.getInstance(agent)
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":
247 agent_obj = self.game_state.player_character
248 else:
249 agent_obj = self.game_state.getObjectById(agent, map_name)
250 if agent_obj:
251 agent_inst = self.game_state.maps[map_name].\
252 agent_layer.getInstance(agent)
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)
260
261 save_file.close()
262
263 def load(self, path, filename):
264 """Loads a saver from a file.
265 @type filename: string
266 @param filename: the name of the file (including path) to load from
267 @return: None"""
268 fname = '/'.join([path, filename])
269
270 try:
271 load_file = open(fname, 'r')
272 except(IOError):
273 sys.stderr.write("Error: Can't find save game file\n")
274 return
275 self.deleteMaps()
276 self.clearAgents()
277
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
286 # Load the current map
287 if self.game_state.current_map_name:
288 self.loadMap(self.game_state.current_map_name)
289 load_file.close()
290
291
292 # Recreate all the behaviours. These can't be saved because FIFE
293 # objects cannot be pickled
294
295 self.placeAgents()
296 self.placePC()
297
298 # In most maps we'll create the PlayerCharacter Instance internally.
299 # In these cases we need a target position
300
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"""
307 logging.debug(position)
308 coord = fife.DoublePoint3D(float(position[0]), float(position[1]), 0)
309 location = fife.Location(self.active_map.agent_layer)
310 location.setMapCoordinates(coord)
311 agent.teleport(location)
312
313 def getObjectAtCoords(self, coords):
314 """Get the object which is at the given coords
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"""
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
326
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
343 else:
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
359 def pause(self, paused):
360 """ Pause/Unpause the game
361 @return: nothing"""
362 if self.active_map:
363 self.active_map.pause(paused)
364
365 def togglePause(self):
366 """ Toggle paused state.
367 @return: nothing"""
368 self.active_map.togglePause()
369
370 def isPaused(self):
371 """Returns wheter the game is paused or not"""
372 return self.active_map.isPaused()
373
374 def readMapFiles(self):
375 """Read all a available map-files and store them"""
376 maps_data = file(self.game_state.maps_file)
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
384 @type agent: dict """
385 from fife.extensions.serializers.xml_loader_tools import loadImportFile
386 if not self.agents.has_key(namespace):
387 self.agents[namespace] = {}
388
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
393 self.agents[namespace].update(agent)
394 object_model = ""
395 if agent_values.has_key("ObjectModel"):
396 object_model = agent_values["ObjectModel"]
397 elif agent_values["ObjectType"] == "MapItem":
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"
401 else:
402 object_model = self.object_db[agent_values["ObjectType"]]["gfx"]
403 import_file = self.agent_import_files[object_model]
404 loadImportFile(self.obj_loader, import_file, self.engine)
405
406 def readAgentsOfMap(self, map_name):
407 """Read the agents of the map
408 @param map_name: Name of the map
409 @type map_name: str """
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
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
431 @return: A dictionary with the agents of the map"""
432 if not self.agents.has_key(map_name):
433 return {}
434 ret_dict = self.agents[map_name].copy()
435 for agent_name, agent_value in self.agents[self.ALL_AGENTS_KEY]\
436 .iteritems():
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
443 @return: A dictionary with the agents of the map """
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):
452 """Load a new map.
453 @type map_name: string
454 @param map_name: Name of the map to load
455 @return: None"""
456 if not map_name in self.game_state.maps:
457 map_file = self.map_files[map_name]
458 new_map = GameMap(self.engine, self)
459 self.game_state.maps[map_name] = new_map
460 new_map.load(map_file)
461
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:
468 if object_type == "MapItem":
469 object_data = self.object_db[agent["ItemType"]]
470 object_id = object_data["gfx"] if object_data.has_key("gfx") \
471 else "generic_item"
472 else:
473 object_id = self.object_db[object_type]["gfx"]
474 map_obj = self.fife_model.getObject(str(object_id), "PARPG")
475 if not map_obj:
476 logging.warning("Object with inst_id={0}, ns=PARPG, "
477 "could not be found. "
478 "Omitting...".format(str(obj_id)))
479
480 x_pos = agent["Position"][0]
481 y_pos = agent["Position"][1]
482 z_pos = agent["Position"][2] if len(agent["Position"]) == 3 \
483 else -0.1 if object_type == "MapItem" \
484 else 0.0
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)
494 inst.setId(inst_id)
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 = {}
508 inst_dict["id"] = inst_id
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"):
550 container_objs = agent["Items"]
551 items = self.createContainerItems(container_objs)
552 inst_dict["items"] = items
553
554 if agent.has_key("ItemType"):
555 if not agent.has_key("item"):
556 item_data = {}
557 item_data["type"] = agent["ItemType"]
558 item_data["ID"] = inst_id
559 item_data = self.createContainerObject(item_data)
560 else:
561 item_data = agent["item"]
562 inst_dict["item"] = item_data
563 inst_dict["item_type"] = agent["ItemType"]
564
565 self.createMapObject(self.active_map.agent_layer, inst_dict)
566
567 def placeAgents(self):
568 """Places the current maps agents """
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
585 # create the PlayerCharacter agent
586 self.active_map.addPC()
587 self.game_state.player_character.start()
588 if agent.has_key("PeopleKnown"):
589 self.game_state.player_character.people_i_know = agent["PeopleKnown"]
590
591 def changeMap(self, map_name, target_position = None):
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()
613 self.game_state.clearObjects()
614 self.game_state.maps = {}
615
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.
625 self.active_map = self.game_state.maps[map_name]
626 self.active_map.makeActive()
627 self.game_state.current_map_name = map_name
628
629 def createMapObject (self, layer, attributes):
630 """Create an object and add it to the current map.
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
637 @return: None"""
638 # create the extra data
639 extra = {}
640 if layer is not None:
641 extra['agent_layer'] = layer
642 attributes = self.checkAttributes(attributes)
643
644 obj = createObject(attributes, extra)
645
646 if obj.trueAttr("PC"):
647 self.addPC(layer, obj)
648 else:
649 self.addObject(layer, obj)
650
651 def addPC(self, layer, player_char):
652 """Add the PlayerCharacter to the map
653 @type layer: fife.Layer
654 @param layer: FIFE layer object exists in
655 @type player_char: PlayerCharacter
656 @param player_char: PlayerCharacter object
657 @type instance: fife.Instance
658 @param instance: FIFE instance of PlayerCharacter
659 @return: None"""
660 # For now we copy the PlayerCharacter,
661 # in the future we will need to copy
662 # PlayerCharacter specifics between the different PlayerCharacter's
663 self.game_state.player_character = player_char
664 self.game_state.player_character.setup()
665 self.game_state.player_character.behaviour.speed = self.settings.parpg.PCSpeed
666
667
668 def addObject(self, layer, obj):
669 """Adds an object to the map.
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
676 @return: None"""
677 ref = self.game_state.getObjectById(obj.ID, \
678 self.game_state.current_map_name)
679 if ref is None:
680 # no, add it to the game state
681 self.game_state.addObject(self.game_state.current_map_name, obj)
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
687
688 if obj.trueAttr("NPC"):
689 # create the agent
690 obj.setup()
691 obj.behaviour.speed = self.settings.parpg.PCSpeed - 1
692 # create the PlayerCharacter agent
693 obj.start()
694 if obj.trueAttr("AnimatedContainer"):
695 # create the agent
696 obj.setup()
697
698 def objectActive(self, ident):
699 """Given the objects ID, pass back the object if it is active,
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)"""
705 for game_object in \
706 self.game_state.getObjectsFromMap(self.game_state.current_map_name):
707 if (game_object.ID == ident):
708 # we found a match
709 return game_object
710 # no match
711 return False
712
713 def movePlayer(self, position):
714 """Code called when the player should move to another location
715 @type position: fife.ScreenPoint
716 @param position: Screen position to move to
717 @return: None"""
718 if(self.pc_run == 1):
719 self.game_state.player_character.run(position)
720 else:
721 self.game_state.player_character.walk(position)
722
723 def teleportAgent(self, agent, position):
724 """Code called when an agent should teleport to another location
725 @type position: fife.ScreenPoint
726 @param position: Screen position to teleport to
727 @return: None"""
728 agent.teleport(position)
729 self.agents[agent.ID]["Position"] = position
730
731 def readObjectDB(self):
732 """Reads the Object Information Database from a file. """
733 database_file = file(self.object_db_file, "r")
734 database = yaml.load_all(database_file)
735 for object_info in database:
736 self.object_db.update(object_info)
737
738 def getAgentImportFiles(self):
739 """Searches the agents directory for import files """
740 files = locateFiles("*.xml", self.objects_directory)
741 for xml_file in files:
742 xml_file = os.path.relpath(xml_file).replace("\\", "/")
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))
749 logging.critical("Error parsing file {0}: "
750 "{1}".format(xml_file, error.msg))
751 sys.exit(1)
752
753 def getDialogues(self):
754 """Searches the dialogue directory for dialogues """
755 files = locateFiles("*.yaml", self.dialogues_directory)
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)
766 except (DialogueFormatError,) as error:
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