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

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

Patch by Aspidites:

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