Mercurial > parpg-core
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} |