Mercurial > parpg-source
diff entities/action.py @ 148:2241722311bf
Moved the action module into the entities package.
Removed the objects package.
author | KarstenBock@gmx.net |
---|---|
date | Sun, 09 Oct 2011 21:02:48 +0200 |
parents | objects/action.py@46570c1ee4ca |
children | 79d6b17b80a3 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/entities/action.py Sun Oct 09 21:02:48 2011 +0200 @@ -0,0 +1,598 @@ +# This file is part of PARPG. + +# PARPG is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# PARPG 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with PARPG. If not, see <http://www.gnu.org/licenses/>. + +#exceptions + +import logging + +logger = logging.getLogger('action') + +from parpg.gui import drag_drop_data as data_drag +from parpg.dialoguecontroller import DialogueController +from parpg.components import container, lockable + + +class NoSuchQuestException(Exception): + """NoQuestException is used when there is no active quest with the id""" + pass + +#classes + +class Action(object): + """Base Action class, to define the structure""" + + + def __init__(self, controller, commands = None): + """Basic action constructor + @param controller: A reference to the GameSceneController. + @type controller: parpg.GameSceneController + @param commands: Special commands that are executed + @type commands: Dictionary + """ + self.commands = commands or () + self.controller = controller + self.model = controller.model + + def execute(self): + """To be overwritten""" + #Check if there are special commands and execute them + for command_data in self.commands: + command = command_data["Command"] + if command == "SetQuestVariable": + quest_id = command_data["ID"] + variable = command_data["Variable"] + value = command_data["Value"] + quest_engine = self.model.game_state.quest_engine + if quest_engine.hasQuest(quest_id): + quest_engine[quest_id].setValue(variable, value) + else: + raise NoSuchQuestException + elif command == "ResetMouseCursor": + self.controller.resetMouseCursor() + elif command == "StopDragging": + data_drag.dragging = False + +class ChangeMapAction(Action): + """A change map scheduled""" + def __init__(self, controller, target_map_name, target_pos, commands=None): + """Initiates a change of the position of the character + possibly flagging a new map to be loaded. + @param controller: A reference to the GameSceneController. + @type controller: parpg.GameSceneController + @param commands: Special commands that are executed + @type commands: Dictionary + @type view: class derived from parpg.ViewBase + @param view: The view + @type target_map_name: String + @param target_map_name: Target map id + @type target_pos: Tuple + @param target_pos: (X, Y) coordinates on the target map. + @return: None""" + super(ChangeMapAction, self).__init__(controller, commands) + self.view = controller.view + self.target_pos = target_pos + self.target_map_name = target_map_name + + def execute(self): + """Executes the map change.""" + self.model.changeMap(self.target_map_name, + self.target_pos) + super(ChangeMapAction, self).execute() + +class OpenAction(Action): + """Open an lockable""" + def __init__(self, controller, lockable, commands=None): + """ + @param controller: A reference to the GameSceneController. + @type controller: parpg.GameSceneController + @param commands: Special commands that are executed + @type commands: Dictionary + @type view: class derived from parpg.ViewBase + @param view: The view + @param lockable: A reference to the lockable + """ + Action.__init__(self, controller, commands) + self.view = controller.view + self.lockable = lockable + + def execute(self): + """Open the lockable.""" + try: + lockable.open(self.lockable.lockable) + self.lockable.fifeagent.behaviour.animate("open") + self.lockable.fifeagent.behaviour.queue_animation("opened", + repeating=True) + except lockable.LockedError: + self.view.hud.createExamineBox(self.lockable.description.view_name, + "Locked") + Action.execute(self) + +class CloseAction(Action): + """Close an lockable""" + def __init__(self, controller, lockable, commands=None): + """ + @param controller: A reference to the GameSceneController. + @type controller: parpg.GameSceneController + @param commands: Special commands that are executed + @type commands: Dictionary + @type view: class derived from parpg.ViewBase + @param view: The view + @param lockable: A reference to the lockable + """ + Action.__init__(self, controller, commands) + self.lockable = lockable + + def execute(self): + """Close the lockable.""" + lockable.close(self.lockable.lockable) + self.lockable.fifeagent.behaviour.animate("close") + self.lockable.fifeagent.behaviour.queue_animation("closed", + repeating=True) + Action.execute(self) + +class UnlockAction(Action): + """Unlocks a lockable.""" + def __init__(self, controller, lockable, commands = None): + """ + @param controller: A reference to the GameSceneController. + @type controller: parpg.GameSceneController + @param commands: Special commands that are executed + @type commands: Dictionary + @param lockable: A reference to the lockable + """ + Action.__init__(self, controller, commands) + self.lockable = lockable + + def execute(self): + """Open the box.""" + lockable.unlock(self.lockable.lockable) + Action.execute(self) + +class LockAction(Action): + """Locks a lockable.""" + def __init__(self, controller, lockable, commands = None): + """ + @param controller: A reference to the GameSceneController. + @type controller: parpg.GameSceneController + @param commands: Special commands that are executed + @type commands: Dictionary + @param lockable: A reference to the lockable + """ + Action.__init__(self, controller, commands) + self.lockable = lockable + self.view = controller.view + + def execute(self): + """Lock the box.""" + try: + lockable.lock(self.lockable.lockable) + except lockable.OpenError: + self.view.hud.createExamineBox(self.lockable.description.view_name, + "Is open") + + Action.execute(self) + + +class ExamineAction(Action): + """Examine an object.""" + def __init__(self, controller, examine_id, examine_name, examine_desc=None, commands=None): + """ + @param controller: A reference to the GameSceneController. + @type controller: parpg.GameSceneController + @param examine_id: An object id + @type examine_id: integer + @param examine_name: An object name + @type examine_name: string + @param examine_desc: A description of the object that will be displayed. + @type examine_desc: string + @param commands: Special commands that are executed + @type commands: Dictionary + """ + super(ExamineAction, self).__init__(controller, commands) + self.view = controller.view + self.examine_id = examine_id + self.examine_name = examine_name + if examine_desc is not None: + self.examine_desc = examine_desc + else: + self.examine_desc = "No Description" + + def execute(self): + """Display the text.""" + action_text = self.examine_desc + self.view.hud.addAction(unicode(action_text)) + logger.debug(action_text) + #this code will cut the line up into smaller lines that will be displayed + place = 25 + while place < len(action_text): + if action_text[place] == ' ': + action_text = action_text[:place] +'\n'+action_text[place:] + place += 26 #plus 1 character to offset the new line + else: place += 1 + self.view.displayObjectText(self.examine_id, unicode(action_text), time=3000) + Action.execute(self) + +class ExamineItemAction(Action): + """Examine an item.""" + def __init__(self, controller, examine_name, examine_desc, commands = None): + """ + @param controller: A reference to the GameSceneController. + @type controller: parpg.GameSceneController + @param commands: Special commands that are executed + @type commands: Dictionary + @type view: class derived from parpg.ViewBase + @param view: The view + @type examine_name: String + @param examine_name: Name of the object to be examined. + @type examine_name: String + @param examine_name: Description of the object to be examined. + """ + super(ExamineItemAction, self).__init__(controller, commands) + self.view = controller.view + self.examine_name = examine_name + self.examine_desc = examine_desc + + def execute(self): + """Display the text.""" + action_text = unicode(self.examine_desc) + self.view.hud.addAction(action_text) + logger.debug(action_text) + Action.execute(self) + +class ExamineContentsAction(Action): + """Examine the contens of an container""" + def __init__(self, controller, container, commands=None): + """ + @param controller: A reference to the GameSceneController. + @type controller: parpg.GameSceneController + @param container: The container + @type container: parpg.entities.General + @param commands: Special commands that are executed + @type commands: Dictionary + """ + Action.__init__(self, controller, commands) + self.view = controller.view + self.container = container + + def execute(self): + """Examine the contents""" + self.view.hud.createBoxGUI(self.container.description.view_name, + self.container.container) + Action.execute(self) + +class ReadAction(Action): + """Read a text.""" + def __init__(self, controller, text_name, text, commands = None): + """ + @param controller: A reference to the GameSceneController. + @type controller: parpg.GameSceneController + @param commands: Special commands that are executed + @type commands: Dictionary + @param view: The view + @type view: class derived from parpg.ViewBase + @param text_name: Name of the object containing the text + @type text_name: String + @param text: Text to be displayied + @type text: String + """ + super(ReadAction, self).__init__(controller, commands) + self.view = controller.view + self.text_name = text_name + self.text = text + + def execute(self): + """Examine the box.""" + action_text = unicode('\n'.join(["You read " + self.text_name + ".", + self.text])) + self.view.hud.addAction(action_text) + logger.debug(action_text) + super(ReadAction, self).execute() + +class TalkAction(Action): + """An action to represent starting a dialogue""" + def __init__(self, controller, npc, commands = None): + """ + @param controller: A reference to the GameSceneController. + @type controller: parpg.GameSceneController + @param commands: Special commands that are executed + @type commands: Dictionary + @type view: class derived from parpg.ViewBase + @param view: The view + @type npc: NonPlayerCharacter + @param npc: NPC to interact with. + """ + super(TalkAction, self).__init__(controller, commands) + self.view = controller.view + self.npc = npc + + def execute(self): + """Talk with the NPC when close enough, otherwise move closer. + @return: None""" + player_char = self.model.game_state.\ + getObjectById("PlayerCharacter").fifeagent + npc_coordinates = self.npc.fifeagent.behaviour.getLocation().\ + getLayerCoordinates() + pc_coordinates = player_char.behaviour.agent.\ + getLocation().getLayerCoordinates() + + distance_squared = (npc_coordinates.x - pc_coordinates.x) *\ + (npc_coordinates.x - pc_coordinates.x) +\ + (npc_coordinates.y - pc_coordinates.y) *\ + (npc_coordinates.y - pc_coordinates.y) + + # If we are too far away, we approach the NPC again + if distance_squared > 2: + player_char.behaviour.approach( + [npc_coordinates.x, npc_coordinates.y], + TalkAction(self.controller, + self.npc, + self.commands + ) + ) + else: + player_char.behaviour.agent.act( + 'stand', + self.npc.fifeagent.behaviour.getLocation() + ) + + if self.npc.dialogue.dialogue is not None: + dialogue_controller = DialogueController( + self.controller.engine, + self.view, + self.model, + self.controller.application + ) + self.controller.application.manager.push_mode( + dialogue_controller + ) + dialogue_controller.startTalk(self.npc) + else: + self.npc.fifeagent.behaviour.agent.say("Leave me alone!", 1000) + + self.model.game_state.getObjectById("PlayerCharacter").\ + fifeagent.behaviour.idle() + self.model.game_state.getObjectById("PlayerCharacter").\ + fifeagent.behaviour.nextAction = None + super(TalkAction, self).execute() + +class UseAction(Action): + """Action for carryable items. It executes special commands that can be only + used on carryable utens""" + + + def __init__(self, controller, item, commands = None): + """ + @param controller: A reference to the GameSceneController. + @type controller: parpg.GameSceneController + @param item: Item on which the action is called + @type item: CarryableItem + @param commands: Special commands that are executed + @type commands: Dictionary + """ + super(UseAction, self).__init__(controller, commands) + self.view = controller.view + self.item = item + + def execute(self): + #Check if there are special commands and execute them + for command_data in self.commands: + command = command_data["Command"] + if command == "ReplaceItem": + object_id = command_data["ID"] + object_type = command_data["ObjectType"] + containable = self.item.containable + new_item = self.model.createItemByType(object_type, + object_id, + self.item.world) + container.put_item(containable.container, + new_item.containable, + containable.slot) + self.model.deleteObject(self.item.general.identifier) + self.item.delete() + self.view.hud.inventory.updateImages() + super(UseAction, self).execute() + +class PickUpAction(Action): + """Action for picking up items from a map""" + + def __init__(self, controller, item, commands = None): + super(PickUpAction, self).__init__(controller, commands) + self.item = item + self.view = controller.view + + def execute(self): + real_item = self.item.containable + self.item.fifeagent = None + player = self.model.game_state.getObjectById("PlayerCharacter") + self.model.moveObject(self.item.general.identifier, None) + self.model.updateObjectDB(self.item.world) + container.put_item(player.container, real_item) + super(PickUpAction, self).execute() + +class DropItemAction(Action): + """Action for dropping an items on a map""" + def __init__(self, controller, item, commands = None): + super(DropItemAction, self).__init__(controller, commands) + self.item = item + + def execute(self): + map_name = self.model.game_state.current_map_name + identifier = self.item.entity.general.identifier + agent_values = self.model.items[identifier] + coords = (self.model.game_state.getObjectById("PlayerCharacter"). + fifeagent.behaviour.getLocation().getExactLayerCoordinates() + ) + agent_values["Position"] = (coords.x, coords.y) + agent_values["Rotation"] = 0 + agent_values["Map"] = map_name + self.model.deleteObject(identifier) + self.model.addAgent(self.model.ALL_AGENTS_KEY, + {identifier: agent_values}) + self.model.placeAgents(self.item.entity.world) + self.model.updateObjectDB(self.item.entity.world) + super(DropItemAction, self).execute() + +class DropItemFromContainerAction(DropItemAction): + """Action for dropping an items from the Inventory to a map""" + + def __init__(self, controller, item, container_gui, commands = None): + super(DropItemFromContainerAction, self).__init__(controller, item, commands) + self.container_gui = container_gui + + def execute(self): + super(DropItemFromContainerAction, self).execute() + container.remove_item(self.item.container, self.item.slot) + self.container_gui.updateImages() + +class BrewBeerAction(Action): + """Action for brewing beer in a pot""" + def __init__(self, controller, pot, commands = None): + super(BrewBeerAction, self).__init__(controller, commands) + self.pot = pot.container + self.view = controller.view + + def execute(self): + """Brew the beer""" + has_water = False + has_yeast = False + has_fruit = False + has_wood = False + has_bottle = False + player_character = (self.model.game_state. + getObjectById("PlayerCharacter").container) + for item in self.pot.children: + if not item: + continue + if item.item_type == "Questionable water": + if has_water: + self.view.hud.addAction(unicode(\ + "Please put only 1 water in the pot")) + return + has_water = True + water_type = 1 + water = item + elif item.item_type == "Pure water": + if has_water: + self.view.hud.addAction(unicode(\ + "Please put only 1 water in the pot")) + return + has_water = True + water_type = 2 + water = item + elif item.item_type == "Grain": + if has_fruit: + self.view.hud.addAction(unicode(\ + "Please put only 1 fruit in the pot")) + return + has_fruit = True + fruit_type = 3 + fruit = item + elif item.item_type == "Wild potato": + if has_fruit: + self.view.hud.addAction(unicode(\ + "Please put only 1 fruit in the pot")) + return + has_fruit = True + fruit_type = 2 + fruit = item + elif item.item_type == "Rotten yam": + if has_fruit: + self.view.hud.addAction(unicode(\ + "Please put only 1 fruit in the pot")) + return + has_fruit = True + fruit_type = 1 + fruit = item + elif item.item_type == "Yeast": + if has_yeast: + self.view.hud.addAction(unicode(\ + "Please put only 1 yeast in the pot")) + return + has_yeast = True + yeast = item + else: + self.view.hud.addAction(unicode( + "Item " + (item.entity.description.view_name) + + " is not needed for brewing beer")) + self.view.hud.addAction(unicode(\ + "Please put only ingredients for the beer in the pot.\ + Things like bottles and wood have to be in your inventory")) + return + wood = container.get_item(player_character, "Wood") + if wood: + has_wood = True + bottle = container.get_item(player_character, "Empty beer bottle") + if bottle: + has_bottle = True + if has_water and has_fruit and has_wood and has_bottle: + container.remove_item(self.pot, water.slot) + container.remove_item(self.pot, fruit.slot) + if has_yeast: + container.remove_item(self.pot, yeast.slot) + container.remove_item(player_character, wood.slot) + new_item = (self.model.createItemByType("Beer", "Beer", + self.pot.entity.world) + ) + container.put_item(player_character, new_item.containable) + self.view.hud.inventory.updateImages() + beer_quality = 0 + if water_type == 1: + if fruit_type == 1: + beer_quality = -1 + elif fruit_type == 2: + beer_quality = 2 + elif fruit_type == 3: + beer_quality = 3 + if water_type == 2: + if fruit_type == 1: + beer_quality = 1 + elif fruit_type == 2: + beer_quality = 3 + elif fruit_type == 3: + beer_quality = 4 + if beer_quality > 0 and has_yeast: + beer_quality += 1 + self.model.game_state.quest_engine.quests["beer"].\ + setValue("beer_quality", beer_quality) + else: + self.view.hud.addAction(unicode( + """For brewing beer you need at least: + In the pot: + Fruit (like grain, potato, yam) + Water + Optionally: + Good quality yeast. + Wild yeast will be used if none present. + In the inventory: + Wood + Empty bottle""")) + super(BrewBeerAction, self).execute() + +ACTIONS = {"ChangeMap":ChangeMapAction, + "Open":OpenAction, + "Close":CloseAction, + "Unlock":UnlockAction, + "Lock":LockAction, + "ExamineItem":ExamineItemAction, + "Examine":ExamineAction, + "Look":ExamineItemAction, + "Read":ReadAction, + "Talk":TalkAction, + "Use":UseAction, + "PickUp":PickUpAction, + "DropFromInventory":DropItemFromContainerAction, + "BrewBeer":BrewBeerAction, + "ExamineContents": ExamineContentsAction, + }