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

Revision 736, 21.5 KB checked in by aspidites, 9 years ago (diff)

Patch by Aspidites:

  • renamed scripts package to parpg
  • renamed parpg module to application
  • removed packaging and other related files (kept locally for reference, will reintroduce similar scripts to resolve bug #275
  • updated all import statements to respect changes above
  • 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, 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        self.examine_desc = examine_desc
196       
197    def execute(self):
198        """Display the text."""
199        action_text = self.examine_desc
200        self.view.hud.addAction(unicode(action_text))
201        print action_text
202        #this code will cut the line up into smaller lines that will be displayed
203        place = 25
204        while place <= len(action_text):
205            if action_text[place] == ' ':
206                action_text = action_text[:place] +'\n'+action_text[place:]
207                place += 26 #plus 1 character to offset the new line
208            else: place += 1
209        self.view.displayObjectText(self.examine_id, unicode(action_text), time=3000)
210
211class ExamineItemAction(Action):
212    """Examine an item."""
213    def __init__(self, controller, examine_name, examine_desc, commands = None):
214        """
215        @param controller: A reference to the GameSceneController.
216        @type controller: parpg.GameSceneController
217        @param commands: Special commands that are executed
218        @type commands: Dictionary
219        @type view: class derived from parpg.ViewBase
220        @param view: The view
221        @type examine_name: String
222        @param examine_name: Name of the object to be examined.
223        @type examine_name: String
224        @param examine_name: Description of the object to be examined.
225        """
226        super(ExamineItemAction, self).__init__(controller, commands)
227        self.view = controller.view
228        self.examine_name = examine_name
229        self.examine_desc = examine_desc
230       
231    def execute(self):
232        """Display the text."""
233        action_text = unicode(self.examine_desc)
234        self.view.hud.addAction(action_text)
235        print action_text
236
237class ReadAction(Action):
238    """Read a text."""
239    def __init__(self, controller, text_name, text, commands = None):
240        """
241        @param controller: A reference to the GameSceneController.
242        @type controller: parpg.GameSceneController
243        @param commands: Special commands that are executed
244        @type commands: Dictionary
245        @param view: The view
246        @type view: class derived from parpg.ViewBase
247        @param text_name: Name of the object containing the text
248        @type text_name: String
249        @param text: Text to be displayied
250        @type text: String
251        """
252        super(ReadAction, self).__init__(controller, commands)
253        self.view = controller.view
254        self.text_name = text_name
255        self.text = text
256       
257    def execute(self):
258        """Examine the box."""
259        action_text = unicode('\n'.join(["You read " + self.text_name + ".", 
260                                         self.text]))
261        self.view.hud.addAction(action_text)
262        print action_text
263        super(ReadAction, self).execute()
264
265class TalkAction(Action):
266    """An action to represent starting a dialogue"""
267    def __init__(self, controller, npc, commands = None):
268        """
269        @param controller: A reference to the GameSceneController.
270        @type controller: parpg.GameSceneController
271        @param commands: Special commands that are executed
272        @type commands: Dictionary
273        @type view: class derived from parpg.ViewBase
274        @param view: The view
275        @type npc: NonPlayerCharacter
276        @param npc: NPC to interact with.
277        """
278        super(TalkAction, self).__init__(controller, commands)
279        self.view = controller.view
280        self.npc = npc
281       
282    def execute(self):
283        """Talk with the NPC when close enough, otherwise move closer.
284           @return: None"""
285        from parpg.dialoguecontroller import DialogueController
286       
287        player_char = self.model.game_state.player_character
288        npc_coordinates = self.npc.getLocation().getLayerCoordinates()
289        pc_coordinates = player_char.behaviour.agent.\
290                            getLocation().getLayerCoordinates()
291       
292        distance_squared = (npc_coordinates.x - pc_coordinates.x) *\
293                           (npc_coordinates.x - pc_coordinates.x) +\
294                           (npc_coordinates.y - pc_coordinates.y) *\
295                           (npc_coordinates.y - pc_coordinates.y)
296       
297        # If we are too far away, we approach the NPC again
298        if distance_squared > 2:
299            player_char.approach([self.npc.getLocation().
300                         getLayerCoordinates().x,
301                         self.npc.getLocation().
302                         getLayerCoordinates().y], 
303                        TalkAction(self.controller,
304                                   self.npc, self.commands))       
305        else:
306            player_char.behaviour.agent.act('stand', self.npc.getLocation())
307   
308            if self.npc.dialogue is not None:
309                dialogue_controller = DialogueController(self.controller.engine,
310                                                         self.view,
311                                                         self.model,
312                                                         self.controller.application)
313                self.controller.application.pushController(dialogue_controller)
314                dialogue_controller.startTalk(self.npc)
315            else:
316                self.npc.behaviour.agent.say("Leave me alone!", 1000)
317               
318            self.model.game_state.player_character.behaviour.idle()
319            self.model.game_state.player_character.nextAction = None
320            super(TalkAction, self).execute()
321
322class UseAction(Action):
323    """Action for carryable items. It executes special commands that can be only
324    used on carryable utens"""
325
326
327    def __init__(self, controller, item, commands = None):
328        """
329        @param controller: A reference to the GameSceneController.
330        @type controller: parpg.GameSceneController
331        @param item: Item on which the action is called
332        @type item: CarryableItem
333        @param commands: Special commands that are executed
334        @type commands: Dictionary
335        """
336        super(UseAction, self).__init__(controller, commands)
337        self.view = controller.view
338        self.item = item
339   
340    def execute(self):
341        #Check if there are special commands and execute them
342        for command_data in self.commands:
343            command = command_data["Command"]
344            if command == "ReplaceItem":
345                object_id = command_data["ID"]
346                object_type = command_data["ObjectType"]
347                container = self.item.in_container
348                inst_dict = {}
349                inst_dict["ID"] = object_id
350                inst_dict["object_type"] = object_type
351                new_item = self.model.createContainerObject(inst_dict)
352                container.replaceItem(self.item, new_item)
353                self.view.hud.inventory.updateInventoryButtons()
354        super(UseAction, self).execute()
355
356class PickUpAction(Action):
357    """Action for picking up items from a map"""
358
359    def __init__(self, controller, map_item, commands = None):
360        super(PickUpAction, self).__init__(controller, commands)
361        self.map_item = map_item
362        self.view = controller.view
363       
364    def execute(self):
365        real_item = self.map_item.item
366        self.model.deleteObject(self.map_item.ID)
367        self.model.game_state.player_character.\
368                                inventory.placeItem(real_item)
369        self.view.hud.inventory.updateInventoryButtons()
370        super(PickUpAction, self).execute()
371
372class DropItemAction(Action):
373    """Action for dropping an items on a map"""
374    def __init__(self, controller, item, commands = None):
375        super(DropItemAction, self).__init__(controller, commands)
376        self.item = item
377       
378    def execute(self):
379        map_name = self.model.game_state.current_map_name
380        map_item_values = {}
381        map_item_values["ViewName"] = self.item.name
382        map_item_values["ObjectType"] = "MapItem"
383        map_item_values["ItemType"] = self.item.item_type
384        map_item_values["Map"] = map_name
385        coords = self.model.game_state.player_character.\
386                                        getLocation().getExactLayerCoordinates()
387        map_item_values["Position"] = (coords.x, coords.y)
388        map_item_values["Rotation"] = 0
389        map_item_values["item"] = self.item
390        agent = {}
391        agent[self.item.ID] = map_item_values
392        self.model.addAgent("All", agent)
393        self.model.placeAgents()
394        super(DropItemAction, self).execute()
395       
396class DropItemFromContainerAction(DropItemAction):
397    """Action for dropping an items from the Inventory to a map"""
398
399    def __init__(self, controller, item, container_gui, commands = None):
400        super(DropItemFromContainerAction, self).__init__(controller, item, commands)
401        self.container_gui = container_gui
402
403    def execute(self):
404        super(DropItemFromContainerAction, self).execute()
405        self.item.in_container.takeItem(self.item)
406        self.container_gui.updateImages()
407       
408class BrewBeerAction(Action):
409    """Action for brewing beer in a pot"""
410    def __init__(self, controller, pot, commands = None):
411        super(BrewBeerAction, self).__init__(controller, commands)
412        self.pot = pot
413        self.view = controller.view
414       
415    def execute(self):
416        """Brew the beer"""
417        has_water = False
418        has_yeast = False
419        has_fruit = False
420        has_wood = False
421        has_bottle = False
422        player_character = self.model.game_state.player_character
423        for item in self.pot.items.itervalues():
424            if item.item_type == "Questionable water":
425                if has_water:
426                    self.view.hud.addAction(unicode(\
427                        "Please put only 1 water in the pot"))
428                    return
429                has_water = True
430                water_type = 1 
431                water = item
432            elif item.item_type == "Pure water":
433                if has_water:
434                    self.view.hud.addAction(unicode(\
435                        "Please put only 1 water in the pot"))
436                    return
437                has_water = True
438                water_type = 2
439                water = item
440            elif item.item_type == "Grain":
441                if has_fruit:
442                    self.view.hud.addAction(unicode(\
443                        "Please put only 1 fruit in the pot"))
444                    return
445                has_fruit = True
446                fruit_type = 3
447                fruit = item
448            elif item.item_type == "Wild potato":
449                if has_fruit:
450                    self.view.hud.addAction(unicode(\
451                        "Please put only 1 fruit in the pot"))
452                    return
453                has_fruit = True
454                fruit_type = 2
455                fruit = item
456            elif item.item_type == "Rotten yam":
457                if has_fruit:
458                    self.view.hud.addAction(unicode(\
459                        "Please put only 1 fruit in the pot"))
460                    return
461                has_fruit = True
462                fruit_type = 1
463                fruit = item
464            elif item.item_type == "Yeast":
465                if has_yeast:
466                    self.view.hud.addAction(unicode(\
467                        "Please put only 1 yeast in the pot"))
468                    return
469                has_yeast = True
470                yeast = item
471            else:
472                self.view.hud.addAction(unicode("Item " + item.name + \
473                                                " is not needed for brewing beer"))
474                self.view.hud.addAction(unicode(\
475                    "Please put only ingredients for the beer in the pot.\
476                    Things like bottles and wood have to be in your inventory"))
477                return
478        wood = player_character.hasItem("Wood")
479        if wood:
480            has_wood = True       
481        bottle = player_character.hasItem("Empty beer bottle")
482        if bottle:
483            has_bottle = True       
484        if has_water and has_fruit and has_wood and has_bottle:
485            self.pot.removeItem(water)
486            self.pot.removeItem(fruit)
487            if has_yeast:
488                self.pot.removeItem(yeast)
489            player_character.inventory.removeItem(wood)
490            inst_dict = {}
491            inst_dict["ID"] = "Beer"
492            inst_dict["object_type"] = "Beer"
493            new_item = self.model.createContainerObject(inst_dict)
494            player_character.inventory.placeItem(new_item)
495            self.view.hud.inventory.updateInventoryButtons()
496            beer_quality = 0
497            if water_type == 1:
498                if fruit_type == 1:
499                    beer_quality = -1
500                elif fruit_type == 2:
501                    beer_quality = 2
502                elif fruit_type == 3:
503                    beer_quality = 3
504            if water_type == 2:
505                if fruit_type == 1:
506                    beer_quality = 1
507                elif fruit_type == 2:
508                    beer_quality = 3
509                elif fruit_type == 3:
510                    beer_quality = 4
511            if beer_quality > 0 and has_yeast:
512                beer_quality += 1
513            self.model.game_state.quest_engine.quests["beer"].\
514                    setValue("beer_quality", beer_quality)
515        else:
516            self.view.hud.addAction(unicode(
517            """For brewing beer you need at least:
518            In the pot:
519                Fruit (like grain, potato, yam)
520                Water
521                Optionally:
522                    Good quality yeast.
523                    Wild yeast will be used if none present.
524            In the inventory:
525                Wood
526                Empty bottle"""))
527        super(BrewBeerAction, self).execute()
528
529ACTIONS = {"ChangeMap":ChangeMapAction, 
530           "Open":OpenAction,
531           "OpenBox":OpenBoxAction, 
532           "Unlock":UnlockBoxAction,
533           "Lock":LockBoxAction,
534           "ExamineItem":ExamineItemAction,
535           "Examine":ExamineAction,
536           "Look":ExamineItemAction,
537           "Read":ReadAction,
538           "Talk":TalkAction,
539           "Use":UseAction,
540           "PickUp":PickUpAction,
541           "DropFromInventory":DropItemFromContainerAction,
542           "BrewBeer":BrewBeerAction}
Note: See TracBrowser for help on using the repository browser.