changeset 560:69d50e751c9a

Lots of changes. - Added the Serializer class - Made exceptions a little more usable - Added actor attributes (not used yet but will be with the combat engine) - Made the quest dialogs more customizable - Many other small changes
author prock@33b003aa-7bff-0310-803a-e67f0ece8222
date Wed, 23 Jun 2010 19:20:24 +0000
parents cccff9b04f57
children 85e8986e7b8f
files demos/rpg/gui/quest.xml demos/rpg/maps/quests.xml demos/rpg/maps/town_objects.xml demos/rpg/run.py demos/rpg/scripts/actors/baseactor.py demos/rpg/scripts/actors/player.py demos/rpg/scripts/actors/questgiver.py demos/rpg/scripts/gamecontroller.py demos/rpg/scripts/guicontroller.py demos/rpg/scripts/misc/exceptions.py demos/rpg/scripts/misc/serializer.py demos/rpg/scripts/objects/baseobject.py demos/rpg/scripts/objects/items.py demos/rpg/scripts/quests/basequest.py demos/rpg/scripts/quests/questmanager.py demos/rpg/scripts/rpg.py demos/rpg/scripts/scene.py
diffstat 17 files changed, 260 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/demos/rpg/gui/quest.xml	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/gui/quest.xml	Wed Jun 23 19:20:24 2010 +0000
@@ -7,7 +7,7 @@
 		</HBox>
 		<HBox>
 			<ScrollArea min_size="400,400" max_size="400,400" size="400,400" vertical_scrollbar="1">
-				<TextBox name="questtext"/>
+				<Label min_size="400,400" max_size="400,400" size="400,400" wrap_text="1" name="questtext"/>
 			</ScrollArea>
 		</HBox>
 		<HBox>
--- a/demos/rpg/maps/quests.xml	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/maps/quests.xml	Wed Jun 23 19:20:24 2010 +0000
@@ -5,8 +5,8 @@
   </Module>
   <Module name="Quiller">
    	<Setting name="questlist" type="list"> test_quest1 ; test_quest2 </Setting>
-   	<Setting name="test_quest1" type="dict"> type : RETURN_ITEM ; name : Test quest ; desc : This is the first quest you will get </Setting>
-   	<Setting name="test_quest2" type="dict"> type : RETURN_ITEM ; name : Second quest ; desc : This is the second quest you will get ; items : GoldStack ; value : 5000 </Setting>
+   	<Setting name="test_quest1" type="dict"> type : RETURN_ITEM ; quest_incomplete_dialog : Come back with 5000 gold! ; quest_complete_dialog : Thank you for finding me 5000 gold. ; name : I need some money! ; desc : Greetings traveler!  I have a quest for you should you choose to accept it.   Go and find me 5000 gold pieces! </Setting>
+   	<Setting name="test_quest2" type="dict"> type : RETURN_ITEM ; quest_incomplete_dialog : Bah! Come back with 5000 gold! ; quest_complete_dialog : Thank you for finding me ANOTHER 5000 gold. ; name : More money! ; desc : Welcome back!  I have a quest for you should you choose to accept it.   Go and find me another 5000 gold pieces! I bet you will find the gold in that temple over there. </Setting>
   </Module>
   <Module name="test_quest1_items">
   	<Setting name="itemlist" type="list"> gold1 </Setting>
--- a/demos/rpg/maps/town_objects.xml	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/maps/town_objects.xml	Wed Jun 23 19:20:24 2010 +0000
@@ -4,6 +4,6 @@
   	<Setting name="objectlist" type="list"> gstack1 ; temple ; Quiller </Setting>
     <Setting name="gstack1" type="dict"> objectname : goldstack ; value : 5000 ; posx : 3.0 ; posy : 3.0 </Setting>
     <Setting name="temple" type="dict"> objectname : templeportal ; dest : level1 ; posx : 3.0 ; posy : -2.0 </Setting>
-    <Setting name="Quiller" type="dict"> objectname : quiller ; posx : 1.0 ; posy : 1.0 </Setting>
+    <Setting name="Quiller" type="dict"> objectname : quiller ; posx : 1.0 ; posy : 1.0 ; noquest_dialog : I've got nothing for you.  Run along now! </Setting>
   </Module>
 </Settings>
--- a/demos/rpg/run.py	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/run.py	Wed Jun 23 19:20:24 2010 +0000
@@ -22,7 +22,6 @@
 #  Free Software Foundation, Inc.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 # ####################################################################
-# This is the rio de hola client for FIFE.
 
 import sys, os, re, math, random, shutil
 
--- a/demos/rpg/scripts/actors/baseactor.py	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/scripts/actors/baseactor.py	Wed Jun 23 19:20:24 2010 +0000
@@ -22,7 +22,6 @@
 #  Free Software Foundation, Inc.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 # ####################################################################
-# This is the rio de hola client for FIFE.
 
 import sys, os, re, math, random, shutil
 
@@ -31,6 +30,7 @@
 
 from scripts.objects.baseobject import ObjectActionListener, BaseGameObject, GameObjectTypes
 from scripts.objects.items import GoldStack
+from scripts.misc.serializer import Serializer
 
 Actions = {'NONE':0,
 		   'PICKUP':1,
@@ -60,7 +60,7 @@
 				else:
 					self._dest.completeQuest()
 			else:
-				self._dest.say("I've got nothing for you...  leave me alone.")
+				self._dest.showNoQuestDialog()
 		else:
 			self._dest.instance.say("Hello there!")
 			
@@ -95,19 +95,76 @@
 			self._object.stand()
 			self._object.performNextAction()
 
+class ActorAttributes(Serializer):
+	def __init__(self, strength=0, dexterity=0, intelligence=0, health=0):
+		self._str = strength
+		self._dex = dexterity
+		self._int = intelligence
+		self._hp = health
+		
+	def serialize(self):
+		lvars['str'] = self._str
+		lvars['dex'] = self._dex
+		lvars['int'] = self._int
+		lvars['hp'] = self._hp
+		
+		return lvars
+		
+	def deserialize(self, valuedict):
+		if valuedict.has_key("str"):
+			self._str = int(valuedict['str'])
+		if valuedict.has_key("dex"):
+			self._dex = int(valuedict['dex'])
+		if valuedict.has_key("int"):
+			self._int = int(valuedict['int'])
+		if valuedict.has_key("hp"):
+			self._hp = int(valuedict['hp'])
+			
+	def _getStrength(self):
+		return self._str
+		
+	def _setStrength(self, strength):
+		self._str = strength
+	
+	def _getDexterity(self):
+		return self._dexterity
+		
+	def _setDexterity(self, dexterity):
+		self._dexterity = dexterity
+		
+	def _getIntelligence(self):
+		return self._int
+		
+	def _setIntelligence(self, intelligence):
+		self._int = intelligence
+		
+	def _getHealth(self):
+		return self._hp
+	
+	def _setHealth(self, health):
+		self._hp = health
+	
+	
+	strength = property(_getStrength, _setStrength)
+	dexterity = property(_getDexterity, _setDexterity)
+	intelligence = property(_getIntelligence, _setIntelligence)
+	health = property(_getHealth, _setHealth)
+			
+
 class Actor(BaseGameObject):
 	def __init__(self, gamecontroller, layer, typename, baseobjectname, instancename, instanceid=None, createInstance=False):
 		super(Actor, self).__init__(gamecontroller, layer, typename, baseobjectname, instancename, instanceid, createInstance)
 
 		self._type = GameObjectTypes["DEFAULT"]
 
-		self._walkspeed = self._gamecontroller.settings.get("RPG", "DefaultActorWalkSpeed", 4.0)
-		
 		self._nextaction = None
 		self._inventory = []
 		self._maxinventoryitems = 20
+
+		self._walkspeed = self._gamecontroller.settings.get("RPG", "DefaultActorWalkSpeed", 4.0)
 		
 		self._gold = 0
+		self._attributes = ActorAttributes()
 		
 		self.stand()
 		
@@ -128,21 +185,28 @@
 			self._nextaction = None
 			
 	def pickUpItem(self, item):
-		if len(self._inventory) >= self._maxinventoryitems:
-			return
+		if self.addItemToInventory(item):
+			item.onPickUp()		
 		else:
-			if type(item) == GoldStack:
-				self._gold += item.value
-			else:
-				self._inventory.append(item)
-		
-			item.onPickUp()
+			#could do something cool like throw the item back on the ground
+			pass
 			
 	def enterPortal(self, portal):
 		if self._id == "player":
 			self._gamecontroller.switchMap(portal.dest)
 		else:
 			self._gamecontroller.scene.removeObjectFromScene(self._id)
+
+	def addItemToInventory(self, item):
+		if len(self._inventory) >= self._maxinventoryitems:
+			return False
+		else:
+			if type(item) == GoldStack:
+				self._gold += item.value
+			else:
+				self._inventory.append(item)
+				
+		return True
 		
 	def removeItemFromInventory(self, itemid):
 		itemtoremove = None
@@ -167,6 +231,9 @@
 			self._gold = int(valuedict['gold'])
 		else:
 			self._gold = 0
+			
+		if valuedict.has_key("walk_speed"):
+			self._walkspeed = float(valuedict['walk_speed'])
 		
 	def _getState(self):
 		return self._state
@@ -189,7 +256,11 @@
 	def _getInventory(self):	
 		return self._inventory
 	
+	def _getAttributes(self):
+		return self._attributes
+	
 	state = property(_getState, _setState)
 	nextaction = property(_getNextAction, _setNextAction)
 	gold = property(_getGold, _setGold)
 	inventory = property(_getInventory)
+	attributes = property(_getAttributes)
--- a/demos/rpg/scripts/actors/player.py	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/scripts/actors/player.py	Wed Jun 23 19:20:24 2010 +0000
@@ -22,7 +22,6 @@
 #  Free Software Foundation, Inc.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 # ####################################################################
-# This is the rio de hola client for FIFE.
 
 import sys, os, re, math, random, shutil
 
--- a/demos/rpg/scripts/actors/questgiver.py	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/scripts/actors/questgiver.py	Wed Jun 23 19:20:24 2010 +0000
@@ -35,6 +35,8 @@
 	def __init__(self, gamecontroller, layer, typename, baseobjectname, instancename, instanceid=None, createInstance=False):
 		super(QuestGiver, self).__init__(gamecontroller, layer, typename, baseobjectname, instancename, instanceid, createInstance)
 		self._type = GameObjectTypes["QUESTGIVER"]
+		
+		self._noquest_dialog = "I've got nothing for you...  leave me alone."
 	
 	def offerNextQuest(self):
 		"""
@@ -54,7 +56,10 @@
 		This is called after the player accepts a quest.  It marks it as active or "in progress".
 		"""
 		self._gamecontroller.questmanager.activateQuest(quest)
-			
+	
+	def showNoQuestDialog(self):
+		self.say(self._noquest_dialog)
+	
 	def completeQuest(self):
 		"""
 		Checks to see if the active quest owned by this QuestGiver is complete and 
@@ -63,7 +68,7 @@
 		for activequest in self._gamecontroller.questmanager.activequests:
 			if activequest.ownerid == self.id:
 				if activequest.checkQuestCompleted(self._gamecontroller.scene.player):
-					self.say("That everything I need.  Thank you!")
+					self.say(activequest._complete_dialog)
 			
 					self._gamecontroller.scene.player.gold = self._gamecontroller.scene.player.gold - activequest.requiredgold
 				
@@ -72,7 +77,7 @@
 			
 					self._gamecontroller.questmanager.completeQuest(activequest)
 				else:
-					self.say("Come back when you have all the items I requested!")
+					self.say(activequest._incomplete_dialog)
 	
 	def haveQuest(self):
 		"""
@@ -80,6 +85,19 @@
 		the player.  Returns False otherwise.
 		"""
 		return bool(self._gamecontroller.questmanager.getNextQuest(self.id)) or bool(self._getActiveQuest())
+
+	def serialize(self):
+		lvars = super(QuestGiver, self).serialize()
+
+		lvars['noquest_dialog'] = self._noquest_dialog
+	
+		return lvars
+
+	def deserialize(self, valuedict):
+		super(QuestGiver, self).deserialize(valuedict)
+		
+		self._noquest_dialog = valuedict['noquest_dialog']
+		
 	
 	def _getActiveQuest(self):
 		"""
--- a/demos/rpg/scripts/gamecontroller.py	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/scripts/gamecontroller.py	Wed Jun 23 19:20:24 2010 +0000
@@ -22,7 +22,6 @@
 #  Free Software Foundation, Inc.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 # ####################################################################
-# This is the rio de hola client for FIFE.
 
 import sys, os, re, math, random, shutil, glob, uuid
 
@@ -305,9 +304,10 @@
 		
 		for filename in glob.glob(os.path.join("saves" , "*.xml")):
 			os.remove(filename)
-			
-		self._questmanager.destroy()
-		self._questmanager.initializeQuests()
+		
+		
+		self._questmanager.reset()
+		self._questmanager.deserialize()
 		
 		mapname = self._settings.get("RPG", "TownMapFile", "town")
 		self.loadMap(mapname)
@@ -358,7 +358,7 @@
 			
 			self._listener.detach()
 			self._scene.destroyScene()
-			self._questmanager.destroy()
+			self._questmanager.reset()
 			
 			self._scene = None
 			self._instancerenderer = None
--- a/demos/rpg/scripts/guicontroller.py	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/scripts/guicontroller.py	Wed Jun 23 19:20:24 2010 +0000
@@ -22,7 +22,6 @@
 #  Free Software Foundation, Inc.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 # ####################################################################
-# This is the rio de hola client for FIFE.
 
 import sys, os, re, math, random, shutil
 
--- a/demos/rpg/scripts/misc/exceptions.py	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/scripts/misc/exceptions.py	Wed Jun 23 19:20:24 2010 +0000
@@ -22,26 +22,50 @@
 #  Free Software Foundation, Inc.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 # ####################################################################
-# This is the rio de hola client for FIFE.
 
+class RPGDemoException(Exception):
+	def __init__(self, msg=None):
+		if msg:
+			self._msg = msg
+		else:
+			self._msg = None
 
-class InvalidCommandError(Exception):
-	def __init__(self):
-		return
+class InvalidCommandError(RPGDemoException):
+	def __init__(self, msg=None):
+		super(InvalidCommandError, self).__init__(msg)
+	
+	def __str__(self):
+		if self._msg:
+			return repr(self._msg)
+		else:
+			return repr("Command not found!")
+		
+class ObjectNotFoundError(RPGDemoException):
+	def __init__(self, msg=None):
+		super(ObjectNotFoundError, self).__init__(msg)
 		
 	def __str__(self):
-		print "","Command not found!"
+		if self._msg:
+			return repr(self._msg)
+		else:
+			return repr("Object was not found!")
 		
-class ObjectNotFoundError(Exception):
-	def __init__(self):
-		return
+class ObjectAlreadyInSceneError(RPGDemoException):
+	def __init__(self, msg=None):
+		super(ObjectAlreadyInSceneError, self).__init__(msg)
 		
 	def __str__(self):
-		print "","Object was not found!"
-		
-class ObjectAlreadyInSceneError(Exception):
-	def __init__(self):
-		return
+		if self._msg:
+			return repr(self._msg)
+		else:
+			return repr("Object was already part of the scene!")
+
+class InstanceNotFoundError(RPGDemoException):
+	def __init__(self, msg=None):
+		super(InstanceNotFoundError, self).__init__(msg)
 		
 	def __str__(self):
-		print "","Object was already part of the scene!"
+		if self._msg:
+			return repr(self._msg)
+		else:
+			return repr("Instance was not found on layer!")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/rpg/scripts/misc/serializer.py	Wed Jun 23 19:20:24 2010 +0000
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+
+# -*- coding: utf-8 -*-
+
+# ####################################################################
+#  Copyright (C) 2005-2010 by the FIFE team
+#  http://www.fifengine.net
+#  This file is part of FIFE.
+#
+#  FIFE is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the
+#  Free Software Foundation, Inc.,
+#  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+# ####################################################################
+
+class Serializer(object):
+	def __init__(self):
+		return
+		
+	def serialize(self):
+		pass
+		
+	def deserialize(self, valuedict=None):
+		pass
+		
+	
+		
--- a/demos/rpg/scripts/objects/baseobject.py	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/scripts/objects/baseobject.py	Wed Jun 23 19:20:24 2010 +0000
@@ -22,13 +22,15 @@
 #  Free Software Foundation, Inc.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 # ####################################################################
-# This is the rio de hola client for FIFE.
 
 import sys, os, re, math, random, shutil
 
 from fife import fife
 from fife.extensions.loaders import loadMapFile
 
+from scripts.misc.exceptions import *
+from scripts.misc.serializer import Serializer
+
 GameObjectTypes = 	{
 						"DEFAULT": 0,
 						"ITEM":1,
@@ -66,7 +68,7 @@
 		pass
 
 
-class BaseGameObject(object):
+class BaseGameObject(Serializer):
 	def __init__(self, gamecontroller, layer, typename, baseobjectname, instancename, instanceid=None, createInstance=False):
 		"""
 		@param gamecontroller: A reference to the master game controller
@@ -129,9 +131,12 @@
 		#This doesnt work
 		#self._instance.get2dGfxVisual().setVisible(True)
 	
-		self._position.x = x
-		self._position.y = y
-		self._createFIFEInstance(self, self._layer)
+		if self._instance:
+			self._setMapPostion(x,y)
+		else:
+			self._position.x = x
+			self._position.y = y
+			self._createFIFEInstance(self, self._layer)
 		
 		self._activated = True
 			
@@ -155,7 +160,10 @@
 		
 		return lvars
 
-	def deserialize(self, valuedict):
+	def deserialize(self, valuedict=None):
+		if not valuedict:
+			return
+		
 		if valuedict.has_key("posx"):
 			x = float(valuedict['posx'])
 		else:
@@ -179,14 +187,16 @@
 		fife.InstanceVisual.create(self._instance)
 			
 		self._instance.thisown = 0
-		
+	
 	def _findFIFEInstance(self, layer):
 		"""
-		@todo: throw InstanceNotFoundError
+		Throws InstanceNotFound if the instance was not found on the specified layer.
 		"""
 		self._instance = self._layer.getInstance(self._id)
 		if self._instance:
-			self._instance.thisown = 0		
+			self._instance.thisown = 0
+		else:
+			raise InstanceNotFoundError(self._id + " was not found on the layer!")
 		
 	def _getLocation(self):
 		return self._instance.getLocation()
--- a/demos/rpg/scripts/objects/items.py	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/scripts/objects/items.py	Wed Jun 23 19:20:24 2010 +0000
@@ -22,7 +22,6 @@
 #  Free Software Foundation, Inc.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 # ####################################################################
-# This is the rio de hola client for FIFE.
 
 import sys, os, re, math, random, shutil
 
--- a/demos/rpg/scripts/quests/basequest.py	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/scripts/quests/basequest.py	Wed Jun 23 19:20:24 2010 +0000
@@ -22,7 +22,6 @@
 #  Free Software Foundation, Inc.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 # ####################################################################
-# This is the rio de hola client for FIFE.
 
 import sys, os, re, math, random, shutil, time
 from datetime import datetime
@@ -38,6 +37,8 @@
 		self._questid = questid
 		self._name = questtitle
 		self._text = questtext
+		self._complete_dialog = "That everything I need.  Thank you!"
+		self._incomplete_dialog = "Come back when you have all the items I requested!"
 		
 	def __eq__(self, other):
 		return self._questid == other.id
--- a/demos/rpg/scripts/quests/questmanager.py	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/scripts/quests/questmanager.py	Wed Jun 23 19:20:24 2010 +0000
@@ -28,8 +28,9 @@
 
 from fife.extensions.fife_settings import Setting
 from scripts.quests.basequest import Quest, ReturnItemQuest, QuestTypes
+from scripts.misc.serializer import Serializer
 
-class QuestManager(object):
+class QuestManager(Serializer):
 	def __init__(self, gamecontroller):
 		self._gamecontroller = gamecontroller
 
@@ -38,8 +39,11 @@
 		self._quests = {}
 		self._activequests = []
 		self._completedquests = []
-		
-	def initializeQuests(self):
+	
+	def serialize(self):
+		pass
+	
+	def deserialize(self, valuedict=None):
 		questfile = self._gamecontroller.settings.get("RPG", "QuestFile", "maps/quests.xml")
 		
 		self._questsettings = Setting(settings_file=questfile)
@@ -47,7 +51,6 @@
 		for identifier in self._questsettings.get("QuestGivers", "list", []):
 			for quest in self._questsettings.get(identifier, "questlist", []):
 					questdict = self._questsettings.get(identifier, quest, {})
-					
 					if questdict['type'] == "RETURN_ITEM":
 						questobj = ReturnItemQuest(identifier, quest, questdict['name'], questdict['desc'])
 						for ritem in self._questsettings.get(quest+"_items", "itemlist", []):
@@ -59,9 +62,15 @@
 					else:
 						questobj = Quest(identifier, quest, questdict['name'], questdict['desc'])
 
+					if questdict.has_key("quest_incomplete_dialog"):
+						questobj._incomplete_dialog = questdict['quest_incomplete_dialog']
+						
+					if questdict.has_key("quest_complete_dialog"):
+						questobj._complete_dialog = questdict['quest_complete_dialog']
+
 					self._gamecontroller.questmanager.addQuest(questobj)
 	
-	def destroy(self):
+	def reset(self):
 		self._quests = {}
 		self._activequests = []
 		self._completedquests = []
@@ -82,17 +91,27 @@
 		return None
 
 	def getNextQuest(self, ownerid):
-		for quest in self._quests[ownerid]:
-			if not quest in self._activequests and not quest in self._completedquests:
-				return quest
-				
+		if self._quests.has_key(ownerid):
+			for quest in self._quests[ownerid]:
+				if not quest in self._activequests and not quest in self._completedquests:
+					return quest
+
 		return None
 		
 	def activateQuest(self, quest):
+		"""
+		Adds the quest to the "active quests" list.  Note that this does NOT affect
+		the quest in any way.  It's just a way of keeping track of which quests
+		the player has accepted.
+		"""
 		if not quest in self._activequests:
 			self._activequests.append(quest)
 		
 	def completeQuest(self, quest):
+		"""
+		Marks the quest as completed.  Note that this does NOT modify the quest in
+		any way.  This is just a way to keep track of completed quests.
+		"""
 		if not quest in self._completedquests:
 			self._completedquests.append(quest)
 		
--- a/demos/rpg/scripts/rpg.py	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/scripts/rpg.py	Wed Jun 23 19:20:24 2010 +0000
@@ -22,7 +22,6 @@
 #  Free Software Foundation, Inc.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 # ####################################################################
-# This is the rio de hola client for FIFE.
 
 import sys, os, re, math, random, shutil, time
 from datetime import datetime
@@ -175,7 +174,7 @@
 	def _pump(self):
 		if self._listener.quit:
 			self._gamecontroller.endGame()
-			self.quitRequested = True
+			self.quit()
 		else:
 			self._gamecontroller.pump()
 			
--- a/demos/rpg/scripts/scene.py	Tue Jun 22 15:41:36 2010 +0000
+++ b/demos/rpg/scripts/scene.py	Wed Jun 23 19:20:24 2010 +0000
@@ -22,7 +22,6 @@
 #  Free Software Foundation, Inc.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 # ####################################################################
-# This is the rio de hola client for FIFE.
 
 import sys, os, re, math, random, shutil, uuid
 
@@ -38,8 +37,10 @@
 from scripts.objects.baseobject import GameObjectTypes, getModuleByType
 from scripts.objects.items import BaseItem, GoldStack, Portal
 from scripts.misc.exceptions import ObjectNotFoundError, ObjectAlreadyInSceneError
+from scripts.misc.serializer import Serializer
 
-class Scene(object):
+
+class Scene(Serializer):
 	def __init__(self, gamecontroller):
 		self._gamecontroller = gamecontroller
 		
@@ -203,25 +204,34 @@
 		location.setMapCoordinates(target_mapcoord)
 		return location
 	
+	def getObject(self, objid):
+		"""
+		Throws ObjectNotFoundError when an object cannot be found on the scene
+		"""
+		
+		try:
+			return self._objectlist[objid]
+		except KeyError:
+			raise ObjectNotFoundError(objid + " was not found on the scene.")
+	
 	def addObjectToScene(self, obj):
 		if not self._objectlist.has_key(obj.id):
 			self._objectlist[obj.id] = obj
 		else:
 			obj.destroy()
 			raise ObjectAlreadyInSceneError
-			
-	def getObject(self, objid):
+
+	def removeObjectFromScene(self, obj):
 		"""
-		@todo: throw ObjectNowFoundError
+		Throws ObjectNotFoundError when an object cannot be found on the scene
 		"""
-		if self._objectlist.has_key(objid):
-			return self._objectlist[objid]
-		else:
-			return None
-	
-	def removeObjectFromScene(self, obj):
+		
 		obj.destroy()
-		del self._objectlist[obj.id]
+		
+		try:
+			del self._objectlist[obj.id]
+		except KeyError:
+			raise ObjectNotFoundError(obj.id + " could not be removed from the scene as it was not found in the scene.")
 		
 	def serialize(self):
 		filename = os.path.join("saves", self._mapname + "_save.xml")