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

Revision 797, 21.6 KB checked in by aspidites, 9 years ago (diff)

Patch by Aspidites:

  • converted print statements to logging messages.
  • all of parpg's log messages go to the same file, but are differenciated by their class names
  • need to find a way to manipulate fife's log level
  • Property svn:eol-style set to native
Line 
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#exceptions
17
18import logging
19
20logger = logging.getLogger('action')
21
22from parpg.gui import drag_drop_data as data_drag
23
24class NoSuchQuestException(Exception):
25    """NoQuestException is used when there is no active quest with the id"""
26    pass
27
28#classes
29
30class Action(object):
31    """Base Action class, to define the structure"""
32
33
34    def __init__(self, controller, commands = None):
35        """Basic action constructor
36        @param controller: A reference to the GameSceneController.
37        @type controller: parpg.GameSceneController
38        @param commands: Special commands that are executed
39        @type commands: Dictionary
40        """
41        self.commands = commands or ()
42        self.controller = controller
43        self.model = controller.model
44   
45    def execute(self):
46        """To be overwritten"""       
47        #Check if there are special commands and execute them
48        for command_data in self.commands:
49            command = command_data["Command"]
50            if command == "SetQuestVariable":
51                quest_id = command_data["ID"]
52                variable = command_data["Variable"]
53                value = command_data["Value"]
54                quest_engine = self.model.game_state.quest_engine
55                if quest_engine.hasQuest(quest_id):
56                    quest_engine[quest_id].setValue(variable, value)
57                else:
58                    raise NoSuchQuestException
59            elif command == "ResetMouseCursor":
60                self.controller.resetMouseCursor()
61            elif command == "StopDragging":
62                data_drag.dragging = False
63               
64class ChangeMapAction(Action):
65    """A change map scheduled"""
66    def __init__(self, controller, target_map_name, target_pos, commands=None):
67        """Initiates a change of the position of the character
68        possibly flagging a new map to be loaded.
69        @param controller: A reference to the GameSceneController.
70        @type controller: parpg.GameSceneController
71        @param commands: Special commands that are executed
72        @type commands: Dictionary
73        @type view: class derived from parpg.ViewBase
74        @param view: The view
75        @type target_map_name: String
76        @param target_map_name: Target map id
77        @type target_pos: Tuple
78        @param target_pos: (X, Y) coordinates on the target map.
79        @return: None"""
80        super(ChangeMapAction, self).__init__(controller, commands)
81        self.view = controller.view
82        self.target_pos = target_pos
83        self.target_map_name = target_map_name
84
85    def execute(self):
86        """Executes the map change."""
87        self.model.changeMap(self.target_map_name,
88                              self.target_pos)
89        super(ChangeMapAction, self).execute()
90
91class OpenAction(Action):
92    """Open a container"""
93    def __init__(self, controller, container, commands=None):
94        """
95        @param controller: A reference to the GameSceneController.
96        @type controller: parpg.GameSceneController
97        @param commands: Special commands that are executed
98        @type commands: Dictionary
99        @type view: class derived from parpg.ViewBase
100        @param view: The view
101        @param container: A reference to the container
102        """
103        super(OpenAction, self).__init__(controller, commands)
104        self.view = controller.view
105        self.container = container
106    def execute(self):
107        """Open the box."""
108        self.view.hud.createBoxGUI(self.container.name, \
109                                              self.container)
110        super(OpenAction, self).execute()
111       
112       
113class OpenBoxAction(OpenAction):
114    """Open a box. Needs to be more generic, but will do for now."""
115    def __init__(self, controller, container, commands = None):
116        """
117        @param controller: A reference to the GameSceneController.
118        @type controller: parpg.GameSceneController
119        @param commands: Special commands that are executed
120        @type commands: Dictionary
121        @type view: class derived from parpg.ViewBase
122        @param view: The view
123        @param container: A reference to the container
124        """
125        super(OpenBoxAction, self).__init__(controller, commands)
126        self.view = controller.view
127        self.container = container
128       
129    def execute(self):
130        """Open the box."""
131        try:
132            self.container.open()
133            super(OpenBoxAction, self).execute()
134
135        except ValueError:
136            self.view.hud.createExamineBox(self.container.name, \
137                                                  "The container is locked")
138       
139class UnlockBoxAction(Action):
140    """Unlocks a box. Needs to be more generic, but will do for now."""
141    def __init__(self, controller, container, commands = None):
142        """
143        @param controller: A reference to the GameSceneController.
144        @type controller: parpg.GameSceneController
145        @param commands: Special commands that are executed
146        @type commands: Dictionary
147        @param container: A reference to the container
148        """
149        super(UnlockBoxAction, self).__init__(controller, commands)
150        self.container = container
151   
152    def execute(self):
153        """Open the box."""
154        self.container.unlock()
155        super(UnlockBoxAction, self).execute()
156       
157class LockBoxAction(Action):
158    """Locks a box. Needs to be more generic, but will do for now."""
159    def __init__(self, controller, container, commands = None):
160        """
161        @param controller: A reference to the GameSceneController.
162        @type controller: parpg.GameSceneController
163        @param commands: Special commands that are executed
164        @type commands: Dictionary
165        @param container: A reference to the container
166        """
167        super(LockBoxAction, self).__init__(controller, commands)
168        self.container = container
169       
170    def execute(self):
171        """Lock the box."""
172        self.container.lock()
173        super(LockBoxAction, self).execute()
174
175
176class ExamineAction(Action):
177    """Examine an object."""
178    def __init__(self, controller, examine_id, examine_name, examine_desc=None, commands=None):
179        """
180        @param controller: A reference to the GameSceneController.
181        @type controller: parpg.GameSceneController
182        @param examine_id: An object id
183        @type examine_id: integer
184        @param examine_name: An object name
185        @type examine_name: string
186        @param examine_desc: A description of the object that will be displayed.
187        @type examine_desc: string
188        @param commands: Special commands that are executed
189        @type commands: Dictionary
190        @type view: class derived from parpg.ViewBase
191        @param view: The view
192       
193        """
194        super(ExamineAction, self).__init__(controller, commands)
195        self.view = controller.view
196        self.examine_id = examine_id
197        self.examine_name = examine_name
198        if examine_desc is not None:
199            self.examine_desc = examine_desc
200        else:
201            self.examine_desc = "No Description"
202       
203    def execute(self):
204        """Display the text."""
205        action_text = self.examine_desc
206        self.view.hud.addAction(unicode(action_text))
207        logger.debug(action_text)
208        #this code will cut the line up into smaller lines that will be displayed
209        place = 25
210        while place <= len(action_text):
211            if action_text[place] == ' ':
212                action_text = action_text[:place] +'\n'+action_text[place:]
213                place += 26 #plus 1 character to offset the new line
214            else: place += 1
215        self.view.displayObjectText(self.examine_id, unicode(action_text), time=3000)
216
217class ExamineItemAction(Action):
218    """Examine an item."""
219    def __init__(self, controller, examine_name, examine_desc, commands = None):
220        """
221        @param controller: A reference to the GameSceneController.
222        @type controller: parpg.GameSceneController
223        @param commands: Special commands that are executed
224        @type commands: Dictionary
225        @type view: class derived from parpg.ViewBase
226        @param view: The view
227        @type examine_name: String
228        @param examine_name: Name of the object to be examined.
229        @type examine_name: String
230        @param examine_name: Description of the object to be examined.
231        """
232        super(ExamineItemAction, self).__init__(controller, commands)
233        self.view = controller.view
234        self.examine_name = examine_name
235        self.examine_desc = examine_desc
236       
237    def execute(self):
238        """Display the text."""
239        action_text = unicode(self.examine_desc)
240        self.view.hud.addAction(action_text)
241        logger.debug(action_text)
242
243class ReadAction(Action):
244    """Read a text."""
245    def __init__(self, controller, text_name, text, commands = None):
246        """
247        @param controller: A reference to the GameSceneController.
248        @type controller: parpg.GameSceneController
249        @param commands: Special commands that are executed
250        @type commands: Dictionary
251        @param view: The view
252        @type view: class derived from parpg.ViewBase
253        @param text_name: Name of the object containing the text
254        @type text_name: String
255        @param text: Text to be displayied
256        @type text: String
257        """
258        super(ReadAction, self).__init__(controller, commands)
259        self.view = controller.view
260        self.text_name = text_name
261        self.text = text
262       
263    def execute(self):
264        """Examine the box."""
265        action_text = unicode('\n'.join(["You read " + self.text_name + ".", 
266                                         self.text]))
267        self.view.hud.addAction(action_text)
268        logger.debug(action_text)
269        super(ReadAction, self).execute()
270
271class TalkAction(Action):
272    """An action to represent starting a dialogue"""
273    def __init__(self, controller, npc, commands = None):
274        """
275        @param controller: A reference to the GameSceneController.
276        @type controller: parpg.GameSceneController
277        @param commands: Special commands that are executed
278        @type commands: Dictionary
279        @type view: class derived from parpg.ViewBase
280        @param view: The view
281        @type npc: NonPlayerCharacter
282        @param npc: NPC to interact with.
283        """
284        super(TalkAction, self).__init__(controller, commands)
285        self.view = controller.view
286        self.npc = npc
287       
288    def execute(self):
289        """Talk with the NPC when close enough, otherwise move closer.
290           @return: None"""
291        from parpg.dialoguecontroller import DialogueController
292       
293        player_char = self.model.game_state.player_character
294        npc_coordinates = self.npc.getLocation().getLayerCoordinates()
295        pc_coordinates = player_char.behaviour.agent.\
296                            getLocation().getLayerCoordinates()
297       
298        distance_squared = (npc_coordinates.x - pc_coordinates.x) *\
299                           (npc_coordinates.x - pc_coordinates.x) +\
300                           (npc_coordinates.y - pc_coordinates.y) *\
301                           (npc_coordinates.y - pc_coordinates.y)
302       
303        # If we are too far away, we approach the NPC again
304        if distance_squared > 2:
305            player_char.approach([self.npc.getLocation().
306                         getLayerCoordinates().x,
307                         self.npc.getLocation().
308                         getLayerCoordinates().y], 
309                        TalkAction(self.controller,
310                                   self.npc, self.commands))       
311        else:
312            player_char.behaviour.agent.act('stand', self.npc.getLocation())
313   
314            if self.npc.dialogue is not None:
315                dialogue_controller = DialogueController(self.controller.engine,
316                                                         self.view,
317                                                         self.model,
318                                                         self.controller.application)
319                self.controller.application.pushController(dialogue_controller)
320                dialogue_controller.startTalk(self.npc)
321            else:
322                self.npc.behaviour.agent.say("Leave me alone!", 1000)
323               
324            self.model.game_state.player_character.behaviour.idle()
325            self.model.game_state.player_character.nextAction = None
326            super(TalkAction, self).execute()
327
328class UseAction(Action):
329    """Action for carryable items. It executes special commands that can be only
330    used on carryable utens"""
331
332
333    def __init__(self, controller, item, commands = None):
334        """
335        @param controller: A reference to the GameSceneController.
336        @type controller: parpg.GameSceneController
337        @param item: Item on which the action is called
338        @type item: CarryableItem
339        @param commands: Special commands that are executed
340        @type commands: Dictionary
341        """
342        super(UseAction, self).__init__(controller, commands)
343        self.view = controller.view
344        self.item = item
345   
346    def execute(self):
347        #Check if there are special commands and execute them
348        for command_data in self.commands:
349            command = command_data["Command"]
350            if command == "ReplaceItem":
351                object_id = command_data["ID"]
352                object_type = command_data["ObjectType"]
353                container = self.item.in_container
354                inst_dict = {}
355                inst_dict["ID"] = object_id
356                inst_dict["object_type"] = object_type
357                new_item = self.model.createContainerObject(inst_dict)
358                container.replaceItem(self.item, new_item)
359                self.view.hud.inventory.updateInventoryButtons()
360        super(UseAction, self).execute()
361
362class PickUpAction(Action):
363    """Action for picking up items from a map"""
364
365    def __init__(self, controller, map_item, commands = None):
366        super(PickUpAction, self).__init__(controller, commands)
367        self.map_item = map_item
368        self.view = controller.view
369       
370    def execute(self):
371        real_item = self.map_item.item
372        self.model.deleteObject(self.map_item.ID)
373        self.model.game_state.player_character.\
374                                inventory.placeItem(real_item)
375        self.view.hud.inventory.updateInventoryButtons()
376        super(PickUpAction, self).execute()
377
378class DropItemAction(Action):
379    """Action for dropping an items on a map"""
380    def __init__(self, controller, item, commands = None):
381        super(DropItemAction, self).__init__(controller, commands)
382        self.item = item
383       
384    def execute(self):
385        map_name = self.model.game_state.current_map_name
386        map_item_values = {}
387        map_item_values["ViewName"] = self.item.name
388        map_item_values["ObjectType"] = "MapItem"
389        map_item_values["ItemType"] = self.item.item_type
390        map_item_values["Map"] = map_name
391        coords = self.model.game_state.player_character.\
392                                        getLocation().getExactLayerCoordinates()
393        map_item_values["Position"] = (coords.x, coords.y)
394        map_item_values["Rotation"] = 0
395        map_item_values["item"] = self.item
396        agent = {}
397        agent[self.item.ID] = map_item_values
398        self.model.addAgent("All", agent)
399        self.model.placeAgents()
400        super(DropItemAction, self).execute()
401       
402class DropItemFromContainerAction(DropItemAction):
403    """Action for dropping an items from the Inventory to a map"""
404
405    def __init__(self, controller, item, container_gui, commands = None):
406        super(DropItemFromContainerAction, self).__init__(controller, item, commands)
407        self.container_gui = container_gui
408
409    def execute(self):
410        super(DropItemFromContainerAction, self).execute()
411        self.item.in_container.takeItem(self.item)
412        self.container_gui.updateImages()
413       
414class BrewBeerAction(Action):
415    """Action for brewing beer in a pot"""
416    def __init__(self, controller, pot, commands = None):
417        super(BrewBeerAction, self).__init__(controller, commands)
418        self.pot = pot
419        self.view = controller.view
420       
421    def execute(self):
422        """Brew the beer"""
423        has_water = False
424        has_yeast = False
425        has_fruit = False
426        has_wood = False
427        has_bottle = False
428        player_character = self.model.game_state.player_character
429        for item in self.pot.items.itervalues():
430            if item.item_type == "Questionable water":
431                if has_water:
432                    self.view.hud.addAction(unicode(\
433                        "Please put only 1 water in the pot"))
434                    return
435                has_water = True
436                water_type = 1 
437                water = item
438            elif item.item_type == "Pure water":
439                if has_water:
440                    self.view.hud.addAction(unicode(\
441                        "Please put only 1 water in the pot"))
442                    return
443                has_water = True
444                water_type = 2
445                water = item
446            elif item.item_type == "Grain":
447                if has_fruit:
448                    self.view.hud.addAction(unicode(\
449                        "Please put only 1 fruit in the pot"))
450                    return
451                has_fruit = True
452                fruit_type = 3
453                fruit = item
454            elif item.item_type == "Wild potato":
455                if has_fruit:
456                    self.view.hud.addAction(unicode(\
457                        "Please put only 1 fruit in the pot"))
458                    return
459                has_fruit = True
460                fruit_type = 2
461                fruit = item
462            elif item.item_type == "Rotten yam":
463                if has_fruit:
464                    self.view.hud.addAction(unicode(\
465                        "Please put only 1 fruit in the pot"))
466                    return
467                has_fruit = True
468                fruit_type = 1
469                fruit = item
470            elif item.item_type == "Yeast":
471                if has_yeast:
472                    self.view.hud.addAction(unicode(\
473                        "Please put only 1 yeast in the pot"))
474                    return
475                has_yeast = True
476                yeast = item
477            else:
478                self.view.hud.addAction(unicode("Item " + item.name + \
479                                                " is not needed for brewing beer"))
480                self.view.hud.addAction(unicode(\
481                    "Please put only ingredients for the beer in the pot.\
482                    Things like bottles and wood have to be in your inventory"))
483                return
484        wood = player_character.hasItem("Wood")
485        if wood:
486            has_wood = True       
487        bottle = player_character.hasItem("Empty beer bottle")
488        if bottle:
489            has_bottle = True       
490        if has_water and has_fruit and has_wood and has_bottle:
491            self.pot.removeItem(water)
492            self.pot.removeItem(fruit)
493            if has_yeast:
494                self.pot.removeItem(yeast)
495            player_character.inventory.removeItem(wood)
496            inst_dict = {}
497            inst_dict["ID"] = "Beer"
498            inst_dict["object_type"] = "Beer"
499            new_item = self.model.createContainerObject(inst_dict)
500            player_character.inventory.placeItem(new_item)
501            self.view.hud.inventory.updateInventoryButtons()
502            beer_quality = 0
503            if water_type == 1:
504                if fruit_type == 1:
505                    beer_quality = -1
506                elif fruit_type == 2:
507                    beer_quality = 2
508                elif fruit_type == 3:
509                    beer_quality = 3
510            if water_type == 2:
511                if fruit_type == 1:
512                    beer_quality = 1
513                elif fruit_type == 2:
514                    beer_quality = 3
515                elif fruit_type == 3:
516                    beer_quality = 4
517            if beer_quality > 0 and has_yeast:
518                beer_quality += 1
519            self.model.game_state.quest_engine.quests["beer"].\
520                    setValue("beer_quality", beer_quality)
521        else:
522            self.view.hud.addAction(unicode(
523            """For brewing beer you need at least:
524            In the pot:
525                Fruit (like grain, potato, yam)
526                Water
527                Optionally:
528                    Good quality yeast.
529                    Wild yeast will be used if none present.
530            In the inventory:
531                Wood
532                Empty bottle"""))
533        super(BrewBeerAction, self).execute()
534
535ACTIONS = {"ChangeMap":ChangeMapAction, 
536           "Open":OpenAction,
537           "OpenBox":OpenBoxAction, 
538           "Unlock":UnlockBoxAction,
539           "Lock":LockBoxAction,
540           "ExamineItem":ExamineItemAction,
541           "Examine":ExamineAction,
542           "Look":ExamineItemAction,
543           "Read":ReadAction,
544           "Talk":TalkAction,
545           "Use":UseAction,
546           "PickUp":PickUpAction,
547           "DropFromInventory":DropItemFromContainerAction,
548           "BrewBeer":BrewBeerAction}
Note: See TracBrowser for help on using the repository browser.