Mercurial > pyntnclick
comparison gamelib/scenes/cryo.py @ 854:3577c51029f1 default tip
Remove Suspended Sentence. pyntnclick is the library we extracted from it
author | Stefano Rivera <stefano@rivera.za.net> |
---|---|
date | Sat, 21 Jun 2014 22:15:54 +0200 |
parents | f95830b58336 |
children |
comparison
equal
deleted
inserted
replaced
853:f95830b58336 | 854:3577c51029f1 |
---|---|
1 """Cryo room where the prisoner starts out.""" | |
2 | |
3 import random | |
4 | |
5 from pyntnclick.i18n import _ | |
6 from pyntnclick.utils import render_text | |
7 from pyntnclick.cursor import CursorSprite | |
8 from pyntnclick.state import Scene, Item, CloneableItem, Thing, Result | |
9 from pyntnclick.scenewidgets import ( | |
10 InteractNoImage, InteractRectUnion, InteractImage, InteractAnimated, | |
11 GenericDescThing, TakeableThing) | |
12 | |
13 from gamelib.scenes.game_constants import PLAYER_ID | |
14 from gamelib.scenes.game_widgets import Door, make_jim_dialog | |
15 | |
16 | |
17 class Cryo(Scene): | |
18 | |
19 FOLDER = "cryo" | |
20 BACKGROUND = "cryo_room.png" | |
21 | |
22 INITIAL_DATA = { | |
23 'greet': True, | |
24 'vandalism_warn': True, | |
25 'sentence': 30, | |
26 } | |
27 | |
28 # sounds that will be played randomly as background noise | |
29 MUSIC = [ | |
30 'drip1.ogg', | |
31 'drip2.ogg', | |
32 'drip3.ogg', | |
33 'creaking.ogg', | |
34 'silent.ogg', | |
35 'silent.ogg', | |
36 ] | |
37 | |
38 def setup(self): | |
39 self.add_item_factory(TitaniumLeg) | |
40 self.add_item_factory(TubeFragment) | |
41 self.add_item_factory(FullBottle) | |
42 self.add_thing(CryoUnitAlpha()) | |
43 self.add_thing(CryoRoomDoor()) | |
44 self.add_thing(CryoComputer()) | |
45 self.add_thing(CryoPipeLeft()) | |
46 self.add_thing(CryoPipeRightTop()) | |
47 self.add_thing(CryoPipeRightBottom()) | |
48 self.add_thing(CryoPools()) | |
49 | |
50 # Flavour items | |
51 # pipes | |
52 self.add_thing(GenericDescThing('cryo.pipes', 1, | |
53 _("These pipes carry cooling fluid to the cryo units."), | |
54 ( | |
55 (552, 145, 129, 66), | |
56 (636, 82, 165, 60), | |
57 (140, 135, 112, 73), | |
58 (11, 63, 140, 67), | |
59 ))) | |
60 self.add_thing(UncuttableCryoPipes()) | |
61 | |
62 # cryo units | |
63 self.add_thing(GenericCryoUnit(2, | |
64 _("An empty cryo chamber."), | |
65 _("Prisoner 81E4-C8900480E635. Embezzlement. 20 years."), | |
66 ( | |
67 (155, 430, 50, 35), | |
68 (125, 450, 60, 35), | |
69 (95, 470, 60, 35), | |
70 (55, 490, 60, 55), | |
71 ))) | |
72 | |
73 self.add_thing(GenericCryoUnit(3, | |
74 _("A working cryo chamber. The frosted glass obscures the details" | |
75 " of the occupant."), | |
76 _("Prisoner 9334-CE1EB0243BAB. Murder. 40 years."), | |
77 ( | |
78 (215, 430, 50, 35), | |
79 (205, 450, 50, 35), | |
80 (185, 470, 50, 35), | |
81 (125, 505, 80, 40), | |
82 ))) | |
83 | |
84 self.add_thing(GenericCryoUnit(4, | |
85 _("A broken cryo chamber. The skeleton inside has been picked" | |
86 " clean."), | |
87 _("Prisoner BFBC-8BF4C6B7492B. Importing illegal alien biomatter." | |
88 " 15 years."), | |
89 ( | |
90 (275, 430, 50, 70), | |
91 (255, 460, 50, 70), | |
92 (235, 490, 50, 60), | |
93 ))) | |
94 | |
95 self.add_thing(GenericCryoUnit(5, | |
96 _("A working cryo chamber. The frosted glass obscures the details " | |
97 "of the occupant."), | |
98 _("Prisoner B520-99495B8C41CE. Copyright infringement. 60 years."), | |
99 ( | |
100 (340, 430, 50, 70), | |
101 (330, 500, 60, 50), | |
102 ))) | |
103 | |
104 self.add_thing(GenericCryoUnit(6, | |
105 _("An empty cryo unit. Recently filled by you."), | |
106 _("Prisoner %s. Safecracking, grand larceny. 30 years.") | |
107 % PLAYER_ID, | |
108 ( | |
109 (399, 426, 70, 56), | |
110 (404, 455, 69, 120), | |
111 ))) | |
112 | |
113 self.add_thing(GenericCryoUnit(7, | |
114 _("An empty cryo unit."), | |
115 _("Prisoner 83F1-CE32D3234749. Spamming. 5 years."), | |
116 ( | |
117 (472, 432, 58, 51), | |
118 (488, 455, 41, 134), | |
119 (517, 487, 42, 93), | |
120 ))) | |
121 | |
122 self.add_thing(GenericCryoUnit(8, | |
123 _("An empty cryo unit."), | |
124 _("Prisoner A455-9DF9F43C43E5. Medical malpractice. 10 years."), | |
125 ( | |
126 (596, 419, 69, 39), | |
127 (616, 442, 82, 40), | |
128 (648, 467, 84, 37), | |
129 (681, 491, 97, 60), | |
130 ))) | |
131 | |
132 def enter(self): | |
133 # Setup music | |
134 pieces = [self.sound.get_music(x) for x in self.MUSIC] | |
135 background_playlist = self.sound.get_playlist(pieces, random=True, | |
136 repeat=True) | |
137 self.sound.change_playlist(background_playlist) | |
138 if self.get_data('greet'): | |
139 self.set_data('greet', False) | |
140 return make_jim_dialog( | |
141 _("Greetings, Prisoner %s. I am the Judicial " | |
142 "Incarceration Monitor. " | |
143 "You have been woken early under the terms of the " | |
144 "emergency conscription act to assist with repairs to " | |
145 "the ship. Your behaviour during this time will " | |
146 "be noted on your record and will be relayed to " | |
147 "prison officials when we reach the destination. " | |
148 "Please report to the bridge.") % PLAYER_ID, self.game) | |
149 | |
150 def leave(self): | |
151 # Stop music | |
152 self.sound.change_playlist(None) | |
153 | |
154 | |
155 class CryoPipeBase(Thing): | |
156 "Base class for cryo pipes that need to be stolen." | |
157 | |
158 INITIAL = "fixed" | |
159 | |
160 INITIAL_DATA = { | |
161 'fixed': True, | |
162 } | |
163 | |
164 def select_interact(self): | |
165 if not self.get_data('fixed'): | |
166 return 'chopped' | |
167 return self.INITIAL | |
168 | |
169 def interact_with_machete(self, item): | |
170 if self.get_data('fixed'): | |
171 self.set_data('fixed', False) | |
172 self.game.add_inventory_item('tube_fragment') | |
173 self.set_interact() | |
174 responses = [Result(_("It takes more effort than one would expect," | |
175 " but eventually the pipe is separated from" | |
176 " the wall."), soundfile="chop-chop.ogg")] | |
177 if self.game.get_current_scene().get_data('vandalism_warn'): | |
178 self.game.get_current_scene().set_data('vandalism_warn', False) | |
179 responses.append(make_jim_dialog( | |
180 _("Prisoner %s. Vandalism is an offence punishable by a " | |
181 "minimum of an additional 6 months to your sentence." | |
182 ) % PLAYER_ID, self.game)) | |
183 return responses | |
184 | |
185 def is_interactive(self, tool=None): | |
186 return self.get_data('fixed') | |
187 | |
188 def interact_without(self): | |
189 if self.get_data('fixed'): | |
190 return Result(_("These pipes aren't attached to the wall very" | |
191 " solidly.")) | |
192 return None | |
193 | |
194 def get_description(self): | |
195 if self.get_data('fixed'): | |
196 return _("These pipes carry cooling fluid to empty cryo units.") | |
197 return _("There used to be a pipe carrying cooling fluid here.") | |
198 | |
199 | |
200 class UncuttableCryoPipes(Thing): | |
201 "Base class for cryo pipes that can't be cut down." | |
202 | |
203 NAME = "cryo.pipes.2" | |
204 | |
205 INTERACTS = { | |
206 "fixed": InteractRectUnion(( | |
207 (2, 130, 44, 394), | |
208 (756, 127, 52, 393),)) | |
209 } | |
210 | |
211 INITIAL = "fixed" | |
212 | |
213 def interact_with_machete(self, item): | |
214 return Result(_("These pipes carry fluid to the working cryo units." | |
215 " Chopping them down doesn't seem sensible.")) | |
216 | |
217 def is_interactive(self, tool=None): | |
218 return True | |
219 | |
220 def interact_without(self): | |
221 return Result( | |
222 _("These pipes aren't attached to the wall very solidly.")) | |
223 | |
224 def get_description(self): | |
225 return _("These pipes carry cooling fluid to the working cryo units.") | |
226 | |
227 | |
228 class TubeFragment(CloneableItem): | |
229 "Obtained after cutting down a cryo room pipe." | |
230 | |
231 NAME = "tube_fragment" | |
232 INVENTORY_IMAGE = "tube_fragment.png" | |
233 CURSOR = CursorSprite('tube_fragment_cursor.png') | |
234 TOOL_NAME = "tube_fragment" | |
235 MAX_COUNT = 3 | |
236 | |
237 | |
238 class CryoPipeLeft(CryoPipeBase): | |
239 "Left cryo pipe." | |
240 | |
241 NAME = "cryo.pipe.left" | |
242 INTERACTS = { | |
243 "fixed": InteractImage(117, 226, "intact_cryo_pipe_left.png"), | |
244 "chopped": InteractNoImage(125, 192, 27, 258), | |
245 } | |
246 | |
247 | |
248 class CryoPipeRightTop(CryoPipeBase): | |
249 "Right cryo pipe, top." | |
250 | |
251 NAME = "cryo.pipe.right.top" | |
252 INTERACTS = { | |
253 "fixed": InteractImage(645, 212, "intact_cryo_pipe_right_top.png"), | |
254 "chopped": InteractNoImage(643, 199, 31, 111), | |
255 } | |
256 | |
257 | |
258 class CryoPipeRightBottom(CryoPipeBase): | |
259 "Right cryo pipe, bottom." | |
260 | |
261 NAME = "cryo.pipe.right.bottom" | |
262 INTERACTS = { | |
263 "fixed": InteractImage(644, 333, "intact_cryo_pipe_right_bottom.png"), | |
264 "chopped": InteractNoImage(644, 333, 31, 107), | |
265 } | |
266 | |
267 | |
268 class TitaniumLeg(Item): | |
269 "Titanium leg, found on a piratical corpse." | |
270 | |
271 NAME = 'titanium_leg' | |
272 INVENTORY_IMAGE = "titanium_femur.png" | |
273 CURSOR = CursorSprite('titanium_femur_cursor.png', 13, 5) | |
274 | |
275 | |
276 class CryoUnitAlpha(Thing): | |
277 "Cryo unit containing titanium leg." | |
278 | |
279 NAME = "cryo.unit.1" | |
280 | |
281 INTERACTS = { | |
282 "unit": InteractRectUnion(( | |
283 (531, 430, 64, 49), | |
284 (560, 460, 57, 47), | |
285 (583, 482, 65, 69), | |
286 (600, 508, 71, 48), | |
287 )) | |
288 } | |
289 | |
290 INITIAL = "unit" | |
291 | |
292 INITIAL_DATA = { | |
293 'contains_titanium_leg': True, | |
294 } | |
295 | |
296 def interact_without(self): | |
297 return Result(detail_view='cryo_detail') | |
298 | |
299 def interact_with_titanium_leg(self, item): | |
300 return Result(_("You hit the chamber that used to hold this very leg." | |
301 " Nothing happens as a result."), | |
302 soundfile="clang2.ogg") | |
303 | |
304 def get_description(self): | |
305 if self.get_data('contains_titanium_leg'): | |
306 return _("A broken cryo chamber, with a poor unfortunate corpse" | |
307 " inside.") | |
308 return _("A broken cryo chamber. The corpse inside is missing a leg.") | |
309 | |
310 | |
311 class GenericCryoUnit(GenericDescThing): | |
312 "Generic Cryo unit" | |
313 | |
314 def __init__(self, number, description, detailed_description, areas): | |
315 super(GenericCryoUnit, self).__init__('cryo.unit', number, | |
316 description, areas) | |
317 self.detailed_description = detailed_description | |
318 | |
319 def is_interactive(self, tool=None): | |
320 return True | |
321 | |
322 def interact_without(self): | |
323 return Result(self.detailed_description) | |
324 | |
325 def get_description(self): | |
326 return self.description | |
327 | |
328 def interact_with_titanium_leg(self, item): | |
329 return Result(random.choice([ | |
330 _("You bang on the chamber with the titanium femur. Nothing" | |
331 " much happens."), | |
332 _("Hitting the cryo unit with the femur doesn't achieve" | |
333 " anything."), | |
334 _("You hit the chamber with the femur. Nothing happens."), | |
335 ]), soundfile="clang2.ogg") | |
336 | |
337 | |
338 class CryoRoomDoor(Door): | |
339 "Door to the cryo room." | |
340 | |
341 SCENE = "cryo" | |
342 | |
343 INTERACTS = { | |
344 "shut": InteractNoImage(290, 260, 99, 152), | |
345 "ajar": InteractImage(290, 260, "door_ajar.png"), | |
346 "open": InteractImage(290, 260, "door_open.png"), | |
347 } | |
348 | |
349 INITIAL = "shut" | |
350 | |
351 INITIAL_DATA = { | |
352 'door': "shut", | |
353 } | |
354 | |
355 def interact_with_titanium_leg(self, item): | |
356 if self.get_data('door') == "ajar": | |
357 self.open_door() | |
358 return Result(_("You wedge the titanium femur into the chain and" | |
359 " twist. With a satisfying *snap*, the chain" | |
360 " breaks and the door opens."), | |
361 soundfile='break.ogg') | |
362 elif self.get_data('door') == "shut": | |
363 text = _("You bang on the door with the titanium femur. It makes a" | |
364 " clanging sound.") | |
365 return Result(text, soundfile='clang.ogg') | |
366 else: | |
367 return Result(_("You wave the femur in the doorway. Nothing" | |
368 " happens.")) | |
369 | |
370 def interact_without(self): | |
371 if self.get_data('door') == "shut": | |
372 self.half_open_door() | |
373 if self.get_data('door') != "open": | |
374 return Result(_("It moves slightly and then stops. A chain on the" | |
375 " other side is preventing it from opening" | |
376 " completely."), soundfile='chain.ogg') | |
377 else: | |
378 self.game.change_scene('map') | |
379 return None | |
380 | |
381 def interact_default(self, item): | |
382 return self.interact_without() | |
383 | |
384 def select_interact(self): | |
385 return self.get_data('door') or self.INITIAL | |
386 | |
387 def half_open_door(self): | |
388 self.set_data('door', "ajar") | |
389 self.set_interact() | |
390 | |
391 def open_door(self): | |
392 self.set_data('door', "open") | |
393 self.set_interact() | |
394 | |
395 def get_description(self): | |
396 if self.get_data('door') == "open": | |
397 return _('An open doorway leads to the rest of the ship.') | |
398 elif self.get_data('door') == "ajar": | |
399 return _("A rusty door. It can't open all the way because of a " | |
400 "chain on the other side.") | |
401 return _('A rusty door. It is currently closed.') | |
402 | |
403 | |
404 class CryoComputer(Thing): | |
405 "Computer in the cryo room." | |
406 | |
407 NAME = "cryo.computer" | |
408 | |
409 INTERACTS = { | |
410 "info": InteractAnimated(416, 290, ["comp_info.png", "comp_info2.png"], | |
411 10), | |
412 "warn": InteractImage(416, 290, "comp_warn.png"), | |
413 "error": InteractImage(416, 290, "comp_error.png"), | |
414 } | |
415 | |
416 INITIAL = "info" | |
417 | |
418 def interact_without(self): | |
419 return Result(detail_view='cryo_comp_detail') | |
420 | |
421 def interact_with_titanium_leg(self, item): | |
422 return Result(_("Hitting it with the leg accomplishes nothing.")) | |
423 | |
424 def get_description(self): | |
425 return _("A computer terminal, with some text on it.") | |
426 | |
427 | |
428 class TitaniumLegThing(TakeableThing): | |
429 "Triangle in the cryo room." | |
430 | |
431 NAME = "cryo.titanium_leg" | |
432 | |
433 INTERACTS = { | |
434 "leg": InteractImage(180, 132, "leg.png"), | |
435 } | |
436 | |
437 INITIAL = "leg" | |
438 ITEM = 'titanium_leg' | |
439 | |
440 def interact_without(self): | |
441 self.game.scenes['cryo'].things['cryo.unit.1'].set_data( | |
442 'contains_titanium_leg', False) | |
443 self.take() | |
444 return Result(_("The skeletal occupant of this cryo unit has an" | |
445 " artificial femur made of titanium. You take it.")) | |
446 | |
447 def get_description(self): | |
448 return _("This femur looks synthetic.") | |
449 | |
450 | |
451 class PlaqueThing(Thing): | |
452 "Plaque on the detailed cryo chamber" | |
453 | |
454 NAME = "cryo.plaque" | |
455 | |
456 INTERACTS = { | |
457 "plaque": InteractNoImage(60, 40, 35, 24), | |
458 } | |
459 | |
460 INITIAL = "plaque" | |
461 | |
462 def interact_without(self): | |
463 return Result( | |
464 _("The plaque is welded to the unit. You can't shift it.")) | |
465 | |
466 def get_description(self): | |
467 return _("'Prisoner 98CC-764E646391EE. War crimes. 45 years.") | |
468 | |
469 | |
470 class FullBottle(Item): | |
471 NAME = 'full_detergent_bottle' | |
472 INVENTORY_IMAGE = 'bottle_full.png' | |
473 CURSOR = CursorSprite('bottle_full_cursor.png', 27, 7) | |
474 | |
475 | |
476 class CryoPools(Thing): | |
477 "Handy for cooling engines" | |
478 | |
479 NAME = 'cryo.pool' | |
480 | |
481 INTERACTS = { | |
482 'pools': InteractRectUnion(( | |
483 (444, 216, 125, 67), | |
484 (44, 133, 74, 107), | |
485 (485, 396, 97, 34), | |
486 )), | |
487 } | |
488 | |
489 INITIAL = 'pools' | |
490 | |
491 def get_description(self): | |
492 return _("Coolant leaks disturbingly from the bulkheads.") | |
493 | |
494 def interact_without(self): | |
495 return Result(_("It's gooey")) | |
496 | |
497 def interact_with_detergent_bottle(self, item): | |
498 self.game.replace_inventory_item(item.name, 'full_detergent_bottle') | |
499 return Result(_("You scoop up some coolant and fill the bottle.")) | |
500 | |
501 | |
502 class CryoCompDetail(Scene): | |
503 | |
504 FOLDER = "cryo" | |
505 BACKGROUND = "comp_info_detail.png" | |
506 NAME = "cryo_comp_detail" | |
507 | |
508 def setup(self): | |
509 background = self.get_image( | |
510 self.FOLDER, self.BACKGROUND) | |
511 # Add the common text strings | |
512 bg = (0, 0, 0, 0) | |
513 fg = 'lightgreen' | |
514 font = 'DejaVuSans-Bold.ttf' | |
515 size = 18 | |
516 | |
517 background.blit(render_text(_("Info"), | |
518 font, 24, fg, bg, self.resource, (90, 25), False), (25, 60)) | |
519 background.blit(render_text(_("Cryo Units Online: 2, 4"), | |
520 font, size, fg, bg, self.resource, (240, 30), False), (15, 120)) | |
521 background.blit(render_text(_("Crew Active: 0"), | |
522 font, size, fg, bg, self.resource, (240, 30), False), (15, 170)) | |
523 background.blit(render_text(_("Current Trip Time: 97558 days"), | |
524 font, size, fg, bg, self.resource, (340, 30), False), (15, 210)) | |
525 background.blit(render_text(_("Expected Time of Arrival:"), | |
526 font, size, fg, bg, self.resource, (340, 30), False), (15, 240)) | |
527 | |
528 self._background_fixed = background.copy() | |
529 self._background_offline = background.copy() | |
530 | |
531 self._background_fixed.blit(render_text(_("397 days"), | |
532 font, size, fg, bg, self.resource, (340, 30), False), (275, 240)) | |
533 | |
534 self._background_offline.blit(render_text( | |
535 _("<Error: Division by Zero Error>"), | |
536 font, size, fg, bg, self.resource, (340, 30), False), (275, 240)) | |
537 | |
538 def draw_background(self, surface): | |
539 if self.game.scenes['engine'].get_data('engine online'): | |
540 surface.blit(self._background_fixed, self.OFFSET, None) | |
541 else: | |
542 surface.blit(self._background_offline, self.OFFSET, None) | |
543 | |
544 | |
545 class CryoUnitWithCorpse(Scene): | |
546 | |
547 FOLDER = "cryo" | |
548 BACKGROUND = "cryo_unit_detail.png" | |
549 NAME = "cryo_detail" | |
550 | |
551 def setup(self): | |
552 self.add_thing(TitaniumLegThing()) | |
553 self.add_thing(PlaqueThing()) | |
554 | |
555 | |
556 SCENES = [Cryo] | |
557 DETAIL_VIEWS = [CryoUnitWithCorpse, CryoCompDetail] |