comparison src/parpg/objects/action.py @ 0:1fd2201f5c36

Initial commit of parpg-core.
author M. George Hansen <technopolitica@gmail.com>
date Sat, 14 May 2011 01:12:35 -0700
parents
children d60f1dab8469
comparison
equal deleted inserted replaced
-1:000000000000 0:1fd2201f5c36
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
18 import logging
19
20 logger = logging.getLogger('action')
21
22 from parpg.gui import drag_drop_data as data_drag
23
24 class NoSuchQuestException(Exception):
25 """NoQuestException is used when there is no active quest with the id"""
26 pass
27
28 #classes
29
30 class 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
64 class 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
91 class 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
113 class 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
139 class 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
157 class 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
176 class 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
217 class 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
243 class 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
271 class 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
328 class 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
362 class 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
378 class 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
402 class 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
414 class 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
535 ACTIONS = {"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}