comparison gamelib/scenes/bridge.py @ 853:f95830b58336

Merge pyntnclick
author Stefano Rivera <stefano@rivera.za.net>
date Sat, 21 Jun 2014 22:04:35 +0200
parents 6a345dcbb209
children
comparison
equal deleted inserted replaced
546:ad4d6ffd25d7 853:f95830b58336
3 import random 3 import random
4 4
5 from pygame.colordict import THECOLORS 5 from pygame.colordict import THECOLORS
6 from pygame.color import Color 6 from pygame.color import Color
7 from pygame.rect import Rect 7 from pygame.rect import Rect
8 from albow.music import change_playlist, get_music, PlayList 8
9 from albow.resource import get_image 9 from pyntnclick.i18n import _
10 10 from pyntnclick.utils import render_text
11 from gamelib.cursor import CursorSprite 11 from pyntnclick.cursor import CursorSprite
12 from gamelib.state import Scene, Item, Thing, Result 12 from pyntnclick.state import Scene, Item, Thing, Result
13 from gamelib.sound import get_current_playlist 13 from pyntnclick.scenewidgets import (
14 from gamelib.constants import DEBUG 14 InteractNoImage, InteractRectUnion, InteractImage, InteractAnimated,
15 from gamelib.scenewidgets import (InteractNoImage, InteractRectUnion, 15 GenericDescThing, TakeableThing, InteractText)
16 InteractImage, InteractAnimated,
17 GenericDescThing)
18 16
19 from gamelib.scenes.game_constants import PLAYER_ID 17 from gamelib.scenes.game_constants import PLAYER_ID
20 from gamelib.scenes.game_widgets import Door, BaseCamera, make_jim_dialog 18 from gamelib.scenes.game_widgets import Door, BaseCamera, make_jim_dialog
21 19
22 20
41 INITIAL_DATA = { 39 INITIAL_DATA = {
42 'ai status': 'online', # online, looping, dead 40 'ai status': 'online', # online, looping, dead
43 'ai panel': 'closed', # closed, open, broken 41 'ai panel': 'closed', # closed, open, broken
44 } 42 }
45 43
46 def __init__(self, state): 44 def setup(self):
47 super(Bridge, self).__init__(state)
48 self.background_playlist = None 45 self.background_playlist = None
49 self.add_item(Superconductor('superconductor')) 46 self.add_item_factory(Superconductor)
50 self.add_item(Stethoscope('stethoscope')) 47 self.add_item_factory(TapedSuperconductor)
48 self.add_item_factory(Stethoscope)
51 self.add_thing(ToMap()) 49 self.add_thing(ToMap())
52 self.add_thing(MonitorCamera()) 50 self.add_thing(MonitorCamera())
53 self.add_thing(MassageChair()) 51 self.add_thing(MassageChair())
54 self.add_thing(MassageChairBase()) 52 self.add_thing(MassageChairBase())
55 self.add_thing(StethoscopeThing()) 53 self.add_thing(StethoscopeThing())
57 self.add_thing(LeftLights()) 55 self.add_thing(LeftLights())
58 self.add_thing(RightLights()) 56 self.add_thing(RightLights())
59 self.add_thing(JimPanel()) 57 self.add_thing(JimPanel())
60 self.add_thing(StarField()) 58 self.add_thing(StarField())
61 self.add_thing(GenericDescThing('bridge.wires', 1, 59 self.add_thing(GenericDescThing('bridge.wires', 1,
62 "The brightly coloured wires contrast with the drab walls.", 60 _("The brightly coloured wires contrast with the drab walls."),
63 ((46, 4, 711, 143),))) 61 ((46, 4, 711, 143),)))
64 self.add_thing(GenericDescThing('bridge.note', 2, 62 self.add_thing(GenericDescThing('bridge.note', 2,
65 "\"Dammit JIM, I'm a doctor, not an engineer!\"", 63 _("\"Dammit JIM, I'm a doctor, not an engineer!\""),
66 ( 64 (
67 (491, 494, 194, 105), 65 (491, 494, 194, 105),
68 (422, 533, 71, 66), 66 (422, 533, 71, 66),
69 ))) 67 )))
70 self.doctor = GenericDescThing('bridge.skel', 3, 68 self.doctor = GenericDescThing('bridge.skel', 3,
71 "A skeleton hangs improbably from the wires.", 69 _("A skeleton hangs improbably from the wires."),
72 ( 70 (
73 (632, 148, 40, 29), 71 (632, 148, 40, 29),
74 (683, 176, 30, 101), 72 (683, 176, 30, 101),
75 (652, 274, 45, 96), 73 (652, 274, 45, 96),
76 (639, 180, 11, 95), 74 (639, 180, 11, 95),
77 )) 75 ))
78 self.add_thing(self.doctor) 76 self.add_thing(self.doctor)
79 77
80 def enter(self): 78 def enter(self):
81 pieces = [get_music(x, prefix='sounds') for x in self.MUSIC] 79 pieces = [self.sound.get_music(x) for x in self.MUSIC]
82 self.background_playlist = PlayList(pieces, random=True, repeat=True) 80 self.background_playlist = self.sound.get_playlist(pieces, random=True,
83 change_playlist(self.background_playlist) 81 repeat=True)
82 self.sound.change_playlist(self.background_playlist)
84 83
85 def leave(self): 84 def leave(self):
86 change_playlist(None) 85 self.sound.change_playlist(None)
87 86
88 87
89 class ToMap(Door): 88 class ToMap(Door):
90 89
91 SCENE = "bridge" 90 SCENE = "bridge"
110 109
111 def interact_without(self): 110 def interact_without(self):
112 return Result(detail_view='bridge_comp_detail') 111 return Result(detail_view='bridge_comp_detail')
113 112
114 def interact_with_titanium_leg(self, item): 113 def interact_with_titanium_leg(self, item):
115 return Result("You can't break the duraplastic screen.") 114 return Result(_("You can't break the duraplastic screen."))
116 115
117 def interact_with_machete(self, item): 116 def interact_with_machete(self, item):
118 return Result("Scratching the screen won't help you.") 117 return Result(_("Scratching the screen won't help you."))
119 118
120 def get_description(self): 119 def get_description(self):
121 return "The main bridge computer screen." 120 return _("The main bridge computer screen.")
122 121
123 122
124 class MassageChairBase(Thing): 123 class MassageChairBase(Thing):
125 "The captain's massage chair, contains superconductor" 124 "The captain's massage chair, contains superconductor"
126 125
139 def interact_without(self): 138 def interact_without(self):
140 return Result(detail_view='chair_detail') 139 return Result(detail_view='chair_detail')
141 140
142 def get_description(self): 141 def get_description(self):
143 if self.get_data('contains_superconductor'): 142 if self.get_data('contains_superconductor'):
144 return ("A top of the line Massage-o-Matic Captain's Executive" 143 return _("A top of the line Massage-o-Matic Captain's Executive"
145 " Command Chair. It's massaging a skeleton.") 144 " Command Chair. It's massaging a skeleton.")
146 return "The chair won't work any more, it has no power." 145 return _("The chair won't work any more, it has no power.")
147 146
148 147
149 class MassageChair(Thing): 148 class MassageChair(Thing):
150 "The captain's massage chair, contains superconductor" 149 "The captain's massage chair, contains superconductor"
151 150
164 } 163 }
165 164
166 INITIAL = 'chair' 165 INITIAL = 'chair'
167 166
168 def get_description(self): 167 def get_description(self):
169 return self.state.current_scene.things['bridge.massagechair_base'] \ 168 base = self.game.get_current_scene().things['bridge.massagechair_base']
170 .get_description() 169 return base.get_description()
171 170
172 def is_interactive(self, tool=None): 171 def is_interactive(self, tool=None):
173 return False 172 return False
174 173
175 174
176 class Stethoscope(Item): 175 class Stethoscope(Item):
177 "Used for cracking safes. Found on the doctor on the chair" 176 "Used for cracking safes. Found on the doctor on the chair"
178 177
178 NAME = 'stethoscope'
179 INVENTORY_IMAGE = 'stethoscope.png' 179 INVENTORY_IMAGE = 'stethoscope.png'
180 CURSOR = CursorSprite('stethoscope.png') 180 CURSOR = CursorSprite('stethoscope.png')
181 181
182 182
183 class StethoscopeThing(Thing): 183 class StethoscopeThing(TakeableThing):
184 "Stehoscope on the doctor" 184 "Stethoscope on the doctor"
185 185
186 NAME = 'bridge.stethoscope' 186 NAME = 'bridge.stethoscope'
187 187
188 INTERACTS = { 188 INTERACTS = {
189 'stethoscope': InteractImage(650, 178, 'hanging_stethoscope.png'), 189 'stethoscope': InteractImage(650, 178, 'hanging_stethoscope.png'),
190 } 190 }
191 191
192 INITIAL = 'stethoscope' 192 INITIAL = 'stethoscope'
193 ITEM = 'stethoscope'
193 194
194 def get_description(self): 195 def get_description(self):
195 return "A stethoscope hangs from the neck of the skeleton." 196 return _("A stethoscope hangs from the neck of the skeleton.")
196 197
197 def interact_without(self): 198 def interact_without(self):
198 self.state.add_inventory_item('stethoscope') 199 self.take()
199 self.scene.remove_thing(self)
200 # Fill in the doctor's rect 200 # Fill in the doctor's rect
201 self.scene.doctor.rect.append(self.rect) 201 self.scene.doctor.rect.append(self.rect)
202 return Result("You pick up the stethoscope and verify that the" 202 return Result(_("You pick up the stethoscope and verify that the"
203 " doctor's heart has stopped. Probably a while ago.") 203 " doctor's heart has stopped. Probably a while ago."))
204 204
205 205
206 class TapedSuperconductor(Item): 206 class TapedSuperconductor(Item):
207 "Used for connecting high-powered parts of the ship up" 207 "Used for connecting high-powered parts of the ship up"
208 208
209 NAME = 'taped_superconductor'
209 INVENTORY_IMAGE = 'superconductor_taped.png' 210 INVENTORY_IMAGE = 'superconductor_taped.png'
210 CURSOR = CursorSprite('superconductor_taped_cursor.png') 211 CURSOR = CursorSprite('superconductor_taped_cursor.png')
211 212
212 213
213 class Superconductor(Item): 214 class Superconductor(Item):
214 "Used for connecting high-powered parts of the ship up" 215 "Used for connecting high-powered parts of the ship up"
215 216
217 NAME = 'superconductor'
216 INVENTORY_IMAGE = 'superconductor_fixed.png' 218 INVENTORY_IMAGE = 'superconductor_fixed.png'
217 CURSOR = CursorSprite('superconductor_fixed.png') 219 CURSOR = CursorSprite('superconductor_fixed.png')
218 220
219 def interact_with_duct_tape(self, item): 221 def interact_with_duct_tape(self, item):
220 taped_superconductor = TapedSuperconductor('taped_superconductor') 222 self.game.replace_inventory_item(self.name, 'taped_superconductor')
221 self.state.add_item(taped_superconductor) 223 return Result(_("You rip off a piece of duct tape and stick it on the"
222 self.state.replace_inventory_item(self.name, taped_superconductor.name) 224 " superconductor. It almost sticks to itself, but you"
223 return Result("You rip off a piece of duct tape and stick it on the" 225 " successfully avoid disaster."))
224 " superconductor. It almost sticks to itself, but you" 226
225 " successfully avoid disaster.") 227
226 228 class SuperconductorThing(TakeableThing):
227
228 class SuperconductorThing(Thing):
229 "Superconductor from the massage chair." 229 "Superconductor from the massage chair."
230 230
231 NAME = 'bridge.superconductor' 231 NAME = 'bridge.superconductor'
232 232
233 INTERACTS = { 233 INTERACTS = {
234 'superconductor': InteractImage(158, 138, 'superconductor.png'), 234 'superconductor': InteractImage(158, 138, 'superconductor.png'),
235 } 235 }
236 236
237 INITIAL = 'superconductor' 237 INITIAL = 'superconductor'
238 238 ITEM = 'superconductor'
239 def interact_without(self): 239
240 self.state.add_inventory_item('superconductor') 240 def interact_without(self):
241 self.state.current_scene.things['bridge.massagechair_base'] \ 241 self.game.scenes['bridge'].things['bridge.massagechair_base'] \
242 .set_data('contains_superconductor', False) 242 .set_data('contains_superconductor', False)
243 self.scene.remove_thing(self) 243 self.take()
244 return (Result("The superconductor module unclips easily."), 244 return (Result(_("The superconductor module unclips easily.")),
245 make_jim_dialog(("Prisoner %s. That chair you've destroyed" 245 make_jim_dialog(_("Prisoner %s. That chair you've destroyed"
246 " was property of the ship's captain. " 246 " was property of the ship's captain. "
247 "You will surely be punished." 247 "You will surely be punished.")
248 % PLAYER_ID), self.state)) 248 % PLAYER_ID, self.game))
249 249
250 250
251 class StarField(Thing): 251 class StarField(Thing):
252 252
253 NAME = 'bridge.stars' 253 NAME = 'bridge.stars'
265 return False 265 return False
266 266
267 267
268 class BlinkingLights(Thing): 268 class BlinkingLights(Thing):
269 269
270 def __init__(self): 270 def setup(self):
271 super(BlinkingLights, self).__init__()
272 self.description = None 271 self.description = None
273 272
274 def is_interactive(self, tool=None): 273 def is_interactive(self, tool=None):
275 return False 274 return False
276 275
277 def leave(self): 276 def leave(self):
278 self.description = random.choice([ 277 self.description = random.choice([
279 "The lights flash in interesting patterns.", 278 _("The lights flash in interesting patterns."),
280 "The flashing lights don't mean anything to you.", 279 _("The flashing lights don't mean anything to you."),
281 "The console lights flash and flicker.", 280 _("The console lights flash and flicker."),
282 ]) 281 ])
283 282
284 def get_description(self): 283 def get_description(self):
285 if not self.description: 284 if not self.description:
286 self.leave() 285 self.leave()
330 329
331 INITIAL = 'closed' 330 INITIAL = 'closed'
332 331
333 def get_description(self): 332 def get_description(self):
334 if self.scene.get_data('ai panel') == 'closed': 333 if self.scene.get_data('ai panel') == 'closed':
335 return "The sign reads 'Warning: Authorized Techinicians Only'." 334 return _("The sign reads 'Warning: Authorized Techinicians Only'.")
336 335
337 def interact_without(self): 336 def select_interact(self):
338 if self.scene.get_data('ai status') == 'online': 337 status = self.scene.get_data('ai panel')
338 return status or self.INITIAL
339
340 def interact_without(self):
341 ai_status = self.state.get_jim_state()
342 if ai_status == 'online':
339 return self.interact_default(None) 343 return self.interact_default(None)
340 elif self.scene.get_data('ai panel') == 'closed': 344 elif self.scene.get_data('ai panel') == 'closed':
341 return Result("You are unable to open the panel with your" 345 return Result(_("You are unable to open the panel with your"
342 " bare hands.") 346 " bare hands."))
343 elif self.scene.get_data('ai panel') == 'open': 347 elif self.scene.get_data('ai panel') == 'open':
344 self.scene.set_data('ai panel', 'broken') 348 self.scene.set_data('ai panel', 'broken')
345 self.scene.set_data('ai status', 'dead') 349 self.state.break_ai()
346 self.set_interact('broken') 350 self.set_interact()
347 return Result("You unplug various important-looking wires.") 351 return Result(_("You unplug various important-looking wires."))
348 352
349 def interact_with_machete(self, item): 353 def interact_with_machete(self, item):
350 if self.scene.get_data('ai status') == 'online': 354 ai_status = self.state.get_jim_state()
355 if ai_status == 'online':
351 return self.interact_default(item) 356 return self.interact_default(item)
352 elif self.scene.get_data('ai panel') == 'closed': 357 elif self.scene.get_data('ai panel') == 'closed':
353 self.scene.set_data('ai panel', 'open') 358 self.scene.set_data('ai panel', 'open')
354 self.set_interact('open') 359 self.set_interact()
355 return Result("Using the machete, you lever the panel off.") 360 return Result(_("Using the machete, you lever the panel off."))
356 elif self.scene.get_data('ai panel') == 'open': 361 elif self.scene.get_data('ai panel') == 'open':
357 self.scene.set_data('ai panel', 'broken') 362 self.scene.set_data('ai panel', 'broken')
358 self.scene.set_data('ai status', 'dead') 363 self.state.break_ai()
359 self.set_interact('broken') 364 self.set_interact()
360 return Result("You smash various delicate components with" 365 return Result(_("You smash various delicate components with"
361 " the machete.") 366 " the machete."))
362 367
363 def interact_default(self, item): 368 def interact_default(self, item):
364 if self.scene.get_data('ai status') == 'online': 369 if self.state.get_jim_state() == 'online':
365 return (Result('You feel a shock from the panel.'), 370 return (Result(_('You feel a shock from the panel.')),
366 make_jim_dialog("Prisoner %s. Please step away from the" 371 make_jim_dialog(_("Prisoner %s. Please step away from the"
367 " panel. You are not an authorized" 372 " panel. You are not an authorized"
368 " technician." % PLAYER_ID, self.state)) 373 " technician.") % PLAYER_ID, self.game))
369 374
370 375
371 class ChairDetail(Scene): 376 class ChairDetail(Scene):
372 377
373 FOLDER = 'bridge' 378 FOLDER = 'bridge'
374 BACKGROUND = 'chair_detail.png' 379 BACKGROUND = 'chair_detail.png'
375 NAME = 'chair_detail' 380 NAME = 'chair_detail'
376 381
377 def __init__(self, state): 382 def setup(self):
378 super(ChairDetail, self).__init__(state)
379 self.add_thing(SuperconductorThing()) 383 self.add_thing(SuperconductorThing())
380 384
381 385
382 # classes related the computer detail 386 # classes related the computer detail
383 387
386 """Tab for log screen""" 390 """Tab for log screen"""
387 391
388 NAME = 'bridge_comp.screen' 392 NAME = 'bridge_comp.screen'
389 393
390 INTERACTS = { 394 INTERACTS = {
391 'log tab': InteractNoImage(100, 53, 94, 37), 395 'log tab': InteractText(100, 53, 94, 37, _("Logs"),
396 'lightgreen', 20, 'DejaVuSans-Bold.ttf', True),
392 } 397 }
393 INITIAL = 'log tab' 398 INITIAL = 'log tab'
394 COMPUTER = 'bridge_comp_detail' 399 COMPUTER = 'bridge_comp_detail'
395 400
396 def is_interactive(self, tool=None): 401 def is_interactive(self, tool=None):
397 return self.state.detail_views[self.COMPUTER].get_data('tab') != 'log' 402 return self.game.detail_views[self.COMPUTER].get_data('tab') != 'log'
398 403
399 def interact_without(self): 404 def interact_without(self):
400 self.state.detail_views[self.COMPUTER].set_data('tab', 'log') 405 self.game.detail_views[self.COMPUTER].set_data('tab', 'log')
401 self.state.detail_views[self.COMPUTER].set_background() 406 self.game.detail_views[self.COMPUTER].set_background()
402 return Result(soundfile='beep550.ogg') 407 return Result(soundfile='beep550.ogg')
403 408
404 409
405 class AlertTab(Thing): 410 class AlertTab(Thing):
406 """Tab for alert screen""" 411 """Tab for alert screen"""
407 412
408 NAME = 'bridge_comp.alert_tab' 413 NAME = 'bridge_comp.alert_tab'
409 414
410 INTERACTS = { 415 INTERACTS = {
411 'alert tab': InteractNoImage(12, 53, 88, 37), 416 'alert tab': InteractText(12, 53, 88, 37, _("Alerts"),
417 'orange', 20, 'DejaVuSans-Bold.ttf', True),
412 } 418 }
413 INITIAL = 'alert tab' 419 INITIAL = 'alert tab'
414 COMPUTER = 'bridge_comp_detail' 420 COMPUTER = 'bridge_comp_detail'
415 421
416 def is_interactive(self, tool=None): 422 def is_interactive(self, tool=None):
417 return (self.state.detail_views[self.COMPUTER].get_data('tab') 423 return (self.game.detail_views[self.COMPUTER].get_data('tab')
418 != 'alert') 424 != 'alert')
419 425
420 def interact_without(self): 426 def interact_without(self):
421 self.state.detail_views[self.COMPUTER].set_data('tab', 'alert') 427 self.game.detail_views[self.COMPUTER].set_data('tab', 'alert')
422 self.state.detail_views[self.COMPUTER].set_background() 428 self.game.detail_views[self.COMPUTER].set_background()
423 return Result(soundfile='beep550.ogg') 429 return Result(soundfile='beep550.ogg')
424 430
425 431
426 class NavTab(Thing): 432 class NavTab(Thing):
427 """Tab for the Navigation screen""" 433 """Tab for the Navigation screen"""
428 434
429 NAME = 'bridge_comp.nav_tab' 435 NAME = 'bridge_comp.nav_tab'
430 436
431 INTERACTS = { 437 INTERACTS = {
432 'nav tab': InteractNoImage(197, 53, 126, 37), 438 'nav tab': InteractText(197, 53, 126, 37, _("Navigation"),
439 'darkblue', 20, 'DejaVuSans-Bold.ttf', True),
433 } 440 }
434 INITIAL = 'nav tab' 441 INITIAL = 'nav tab'
435 COMPUTER = 'bridge_comp_detail' 442 COMPUTER = 'bridge_comp_detail'
436 443
437 def is_interactive(self, tool=None): 444 def is_interactive(self, tool=None):
438 return self.state.detail_views[self.COMPUTER].get_data('tab') != 'nav' 445 return self.game.detail_views[self.COMPUTER].get_data('tab') != 'nav'
439 446
440 def interact_without(self): 447 def interact_without(self):
441 self.state.detail_views[self.COMPUTER].set_data('tab', 'nav') 448 self.game.detail_views[self.COMPUTER].set_data('tab', 'nav')
442 self.state.detail_views[self.COMPUTER].set_background() 449 self.game.detail_views[self.COMPUTER].set_background()
443 return Result(soundfile='beep550.ogg') 450 return Result(soundfile='beep550.ogg')
444 451
445 452
446 class DestNavPageLine(Thing): 453 class DestNavPageLine(Thing):
447 """The destination navigation lines.""" 454 """The destination navigation lines."""
448 455
449 INITIAL = 'line' 456 INITIAL = 'line'
450 COMPUTER = 'bridge_comp_detail' 457 COMPUTER = 'bridge_comp_detail'
451 458
452 def __init__(self, number, rect, ai_blocked): 459 def __init__(self, number, rect, ai_blocked, dest):
453 super(DestNavPageLine, self).__init__() 460 super(DestNavPageLine, self).__init__()
454 self.name = 'bridge_comp.nav_line%s' % number 461 self.name = 'bridge_comp.nav_line%s' % number
455 if DEBUG: 462 # set debugging higlight color for when DEBUG is on.
456 self._interact_hilight_color = Color(THECOLORS.keys()[number]) 463 self._interact_hilight_color = Color(THECOLORS.keys()[number])
457 r = Rect(rect) 464 r = Rect(rect)
465 # We dynamically generate the interact rect here.
458 self.interacts = {} 466 self.interacts = {}
459 self.interacts['line'] = InteractNoImage(r.x, r.y, r.w, r.h) 467 self.interacts['line'] = InteractText(r.x, r.y, r.w, r.h,
468 dest, 'darkblue', 16, 'DejaVuSans-Bold.ttf', False)
460 # Whether JIM blocks this 469 # Whether JIM blocks this
461 self.ai_blocked = ai_blocked 470 self.ai_blocked = ai_blocked
462 self.set_interact('line') 471 self.set_interact()
463 472
464 def is_interactive(self, tool=None): 473 def is_interactive(self, tool=None):
465 return self.state.detail_views[self.COMPUTER].get_data('tab') == 'nav' 474 return self.game.detail_views[self.COMPUTER].get_data('tab') == 'nav'
466 475
467 def interact_without(self): 476 def interact_without(self):
468 if self.state.scenes['bridge'].get_data('ai status') == 'online': 477 if self.game.scenes['bridge'].get_data('ai status') == 'online':
469 return make_jim_dialog("You are not authorized to change the" 478 return make_jim_dialog(_("You are not authorized to change the"
470 " destination.", self.state) 479 " destination."), self.game)
471 if not self.ai_blocked: 480 if not self.ai_blocked:
472 return Result("There's no good reason to choose to go to the" 481 return Result(_("There's no good reason to choose to go to the"
473 " penal colony.") 482 " penal colony."))
474 if self.state.scenes['bridge'].get_data('ai status') == 'looping': 483 if self.game.scenes['bridge'].get_data('ai status') == 'looping':
475 return Result("You could change the destination, but when JIM" 484 return Result(_("You could change the destination, but when JIM"
476 " recovers, it'll just get reset.") 485 " recovers, it'll just get reset."))
477 if self.state.scenes['bridge'].get_data('ai status') == 'dead': 486 if self.game.scenes['bridge'].get_data('ai status') == 'dead':
478 return Result("You change the destination.", 487 return Result(_("You change the destination."),
479 soundfile="beep550.ogg", end_game=True) 488 soundfile="beep550.ogg", end_game=True)
480 489
481 490
482 class CompUpButton(Thing): 491 class CompUpButton(Thing):
483 """Up button on log screen""" 492 """Up button on log screen"""
489 } 498 }
490 INITIAL = 'up' 499 INITIAL = 'up'
491 COMPUTER = 'bridge_comp_detail' 500 COMPUTER = 'bridge_comp_detail'
492 501
493 def is_interactive(self, tool=None): 502 def is_interactive(self, tool=None):
494 tab = self.state.detail_views[self.COMPUTER].get_data('tab') 503 tab = self.game.detail_views[self.COMPUTER].get_data('tab')
495 page = self.state.detail_views[self.COMPUTER].get_data('log page') 504 page = self.game.detail_views[self.COMPUTER].get_data('log page')
496 return tab == 'log' and page > 0 505 return tab == 'log' and page > 0
497 506
498 def interact_without(self): 507 def interact_without(self):
499 page = self.state.detail_views[self.COMPUTER].get_data('log page') 508 page = self.game.detail_views[self.COMPUTER].get_data('log page')
500 self.state.detail_views[self.COMPUTER].set_data('log page', page - 1) 509 self.game.detail_views[self.COMPUTER].set_data('log page', page - 1)
501 self.state.detail_views[self.COMPUTER].set_background() 510 self.game.detail_views[self.COMPUTER].set_background()
502 return Result(soundfile='beep550.ogg') 511 return Result(soundfile='beep550.ogg')
503 512
504 513
505 class CompDownButton(Thing): 514 class CompDownButton(Thing):
506 """Down button on log screen""" 515 """Down button on log screen"""
512 } 521 }
513 INITIAL = 'down' 522 INITIAL = 'down'
514 COMPUTER = 'bridge_comp_detail' 523 COMPUTER = 'bridge_comp_detail'
515 524
516 def is_interactive(self, tool=None): 525 def is_interactive(self, tool=None):
517 tab = self.state.detail_views[self.COMPUTER].get_data('tab') 526 tab = self.game.detail_views[self.COMPUTER].get_data('tab')
518 page = self.state.detail_views[self.COMPUTER].get_data('log page') 527 page = self.game.detail_views[self.COMPUTER].get_data('log page')
519 max_page = self.state.detail_views[self.COMPUTER].get_data('max page') 528 max_page = self.game.detail_views[self.COMPUTER].get_data('max page')
520 return tab == 'log' and (page + 1) < max_page 529 return tab == 'log' and (page + 1) < max_page
521 530
522 def interact_without(self): 531 def interact_without(self):
523 page = self.state.detail_views[self.COMPUTER].get_data('log page') 532 page = self.game.detail_views[self.COMPUTER].get_data('log page')
524 self.state.detail_views[self.COMPUTER].set_data('log page', page + 1) 533 self.game.detail_views[self.COMPUTER].set_data('log page', page + 1)
525 self.state.detail_views[self.COMPUTER].set_background() 534 self.game.detail_views[self.COMPUTER].set_background()
526 return Result(soundfile='beep550.ogg') 535 return Result(soundfile='beep550.ogg')
527 536
528 537
529 class MonitorCamera(BaseCamera): 538 class MonitorCamera(BaseCamera):
530 "A camera on the bridge" 539 "A camera on the bridge"
545 FOLDER = 'bridge' 554 FOLDER = 'bridge'
546 NAME = 'bridge_comp_detail' 555 NAME = 'bridge_comp_detail'
547 556
548 ALERT_BASE = 'comp_alert_base.png' 557 ALERT_BASE = 'comp_alert_base.png'
549 ALERTS = { 558 ALERTS = {
550 'ai looping': 'comp_alert_ai_looping.png', 559 'hull breach': _("Hull breach detected: Engine Room"),
551 'ai offline': 'comp_alert_ai_offline.png', 560 'ai looping': _("AI Status: 3D scene reconstruction failed."
552 'engine offline': 'comp_alert_engine_offline.png', 561 " Recovery in progress"),
553 'life support': 'comp_alert_life_support.png', 562 'ai offline': _("AI System Offline"),
554 'life support partial': 'comp_alert_life_support_partial.png', 563 'engine offline': _("Engine Offline"),
564 'life support': _("Life Support System: 20% operational"),
565 'life support partial': _("Life Support System: 40% operational"),
555 } 566 }
556 567
557 # Point to start drawing changeable alerts 568 # Point to start drawing changeable alerts
558 ALERT_OFFSET = (16, 140) 569 ALERT_OFFSET = (16, 100)
559 ALERT_SPACING = 4 570 ALERT_SPACING = 4
560 571
561 LOGS = ['comp_log_start.png', 'comp_log_1.png', 572 LOG_BACKGROUND = 'comp_log_start.png'
562 'comp_log_end.png'] 573
563 574 LOGS = [_("<Error: Log corrupted. Unable to open Log>")]
564 NAVIGATION = { 575
565 'engine offline': 'bridge_nav_engine.png', 576 NAVIGATION = 'bridge_nav_base.png'
566 'life support': 'bridge_nav_life_support.png', 577
567 'final': 'bridge_nav_dest.png', 578 NAV_MESSAGES = {
579 'engine offline': [
580 _("Engine Offline: Navigation Disabled")],
581 'life support': [
582 _("Life Support Marginal."),
583 _("Emergency Navigation Protocol Engaged."),
584 '',
585 _("Destination locked to:"),
586 _("Bounty Penal Colony Space Port, New South Australia")],
568 } 587 }
569 588
570 BACKGROUND = ALERT_BASE 589 BACKGROUND = ALERT_BASE
571 590
572 INITIAL_DATA = { 591 INITIAL_DATA = {
573 'tab': 'alert', 592 'tab': 'alert',
574 'log page': 0, 593 'log page': 0,
575 'max page': len(LOGS), 594 'max page': len(LOGS),
576 } 595 }
577 596
578 def __init__(self, state): 597 def setup(self):
579 super(BridgeCompDetail, self).__init__(state)
580
581 self.add_thing(LogTab()) 598 self.add_thing(LogTab())
582 self.add_thing(AlertTab()) 599 self.add_thing(AlertTab())
583 self.add_thing(NavTab()) 600 self.add_thing(NavTab())
584 #self.add_thing(CompUpButton()) 601 #self.add_thing(CompUpButton())
585 #self.add_thing(CompDownButton()) 602 #self.add_thing(CompDownButton())
586 self._scene_playlist = None 603 self._scene_playlist = None
587 self._alert = get_image(self.FOLDER, self.ALERT_BASE) 604 self._alert = self.get_image(self.FOLDER, self.ALERT_BASE)
588 self._alert_messages = {} 605 self._alert_messages = {}
589 self._nav_messages = {} 606 self._nav_messages = {}
590 for key, name in self.ALERTS.iteritems(): 607 for key, text in self.ALERTS.iteritems():
591 self._alert_messages[key] = get_image(self.FOLDER, name) 608 self._alert_messages[key] = render_text(text,
592 for key, name in self.NAVIGATION.iteritems(): 609 'DejaVuSans-Bold.ttf', 18, 'orange', (0, 0, 0, 0),
593 self._nav_messages[key] = get_image(self.FOLDER, name) 610 self.resource, (600, 25), False)
611 self._nav_background = self.get_image(self.FOLDER, self.NAVIGATION)
612 #for key, name in self.NAVIGATION.iteritems():
613 # self._nav_messages[key] = self.get_image(self.FOLDER, name)
594 self._nav_lines = [] 614 self._nav_lines = []
595 self._nav_lines.append(DestNavPageLine(1, (14, 99, 595, 30), False)) 615 self._nav_lines.append(DestNavPageLine(1, (12, 99, 610, 25), False,
596 self._nav_lines.append(DestNavPageLine(2, (14, 135, 595, 30), True)) 616 _("1. Bounty Penal Colony Space Port, New South Australia"
597 self._nav_lines.append(DestNavPageLine(3, (14, 167, 595, 30), True)) 617 " (397 days)")))
598 self._nav_lines.append(DestNavPageLine(4, (14, 203, 595, 30), True)) 618 self._nav_lines.append(DestNavPageLine(2, (12, 135, 610, 25), True,
599 self._nav_lines.append(DestNavPageLine(5, (14, 239, 595, 30), True)) 619 _("2. Hedonia Space Station (782 days)")))
600 self._logs = [get_image(self.FOLDER, x) for x in self.LOGS] 620 self._nav_lines.append(DestNavPageLine(3, (12, 167, 610, 25), True,
621 _("3. Spinosa Health Resort, Prunus Secundus (1231 days)")))
622 self._nav_lines.append(DestNavPageLine(4, (12, 203, 610, 25), True,
623 _("4. Achene Space Port, Indica Prspinosame (1621 days)")))
624 self._nav_lines.append(DestNavPageLine(5, (12, 239, 610, 25), True,
625 _("5. Opioid Space Port, Gelatinosa Prime (1963 days)")))
626 self._log_background = self.get_image(self.FOLDER, self.LOG_BACKGROUND)
627 self._logs = []
628 for text in self.LOGS:
629 log_page = self._log_background.copy()
630 log_page.blit(render_text(text, 'DejaVuSans-Bold.ttf', 18,
631 'lightgreen', (0, 0, 0, 0), self.resource, (600, 25), False),
632 self.ALERT_OFFSET)
633 self._logs.append(log_page)
601 634
602 def enter(self): 635 def enter(self):
603 self._scene_playlist = get_current_playlist() 636 self._scene_playlist = self.sound.get_current_playlist()
604 change_playlist(None) 637 self.sound.change_playlist(None)
605 self.set_background() 638 self.set_background()
606 639
607 def leave(self): 640 def leave(self):
608 change_playlist(self._scene_playlist) 641 self.sound.change_playlist(self._scene_playlist)
609 642
610 def set_background(self): 643 def set_background(self):
611 if self.get_data('tab') == 'alert': 644 if self.get_data('tab') == 'alert':
612 self._clear_navigation() 645 self._clear_navigation()
613 self._background = self._alert 646 self._background = self._alert.copy()
647 self._draw_alerts()
614 elif self.get_data('tab') == 'log': 648 elif self.get_data('tab') == 'log':
615 self._clear_navigation() 649 self._clear_navigation()
616 self._background = self._logs[self.get_data('log page')] 650 self._background = self._logs[self.get_data('log page')].copy()
617 elif self.get_data('tab') == 'nav': 651 elif self.get_data('tab') == 'nav':
618 self._background = self._get_nav_page() 652 self._background = self._get_nav_page()
619 653
620 def _clear_navigation(self): 654 def _clear_navigation(self):
621 "Remove navigation things if necessary" 655 "Remove navigation things if necessary"
623 if thing.name in self.things.keys(): 657 if thing.name in self.things.keys():
624 # Much fiddling to do the right thing when we reinsert it 658 # Much fiddling to do the right thing when we reinsert it
625 del self.things[thing.name] 659 del self.things[thing.name]
626 thing.scene = None 660 thing.scene = None
627 661
662 def _draw_nav_text(self, key):
663 surface = self._nav_background.copy()
664 xpos, ypos = self.ALERT_OFFSET
665 for line in self.NAV_MESSAGES[key]:
666 text = render_text(line, 'DejaVuSans-Bold.ttf', 18,
667 'darkblue', (0, 0, 0, 0), self.resource, (600, 25), False)
668 surface.blit(text, (xpos, ypos))
669 ypos = ypos + text.get_height() + self.ALERT_SPACING
670 return surface
671
628 def _get_nav_page(self): 672 def _get_nav_page(self):
629 if not self.state.scenes['engine'].get_data('engine online'): 673 if not self.game.scenes['engine'].get_data('engine online'):
630 return self._nav_messages['engine offline'] 674 return self._draw_nav_text('engine offline')
631 elif (not self.state.scenes['mess'].get_data('life support status') 675 elif (not self.game.scenes['mess'].get_data('life support status')
632 == 'fixed'): 676 == 'fixed'):
633 return self._nav_messages['life support'] 677 return self._draw_nav_text('life support')
634 else: 678 else:
635 for thing in self._nav_lines: 679 for thing in self._nav_lines:
636 if thing.name not in self.things: 680 if thing.name not in self.things:
637 self.add_thing(thing) 681 self.add_thing(thing)
638 return self._nav_messages['final'] 682 return self._nav_background.copy()
639 683
640 def _draw_alerts(self, surface): 684 def _draw_alerts(self):
641 xpos, ypos = self.ALERT_OFFSET 685 xpos, ypos = self.ALERT_OFFSET
642 if self.state.scenes['bridge'].get_data('ai status') == 'looping': 686 self._background.blit(self._alert_messages['hull breach'],
643 surface.blit(self._alert_messages['ai looping'], (xpos, ypos)) 687 (xpos, ypos))
688 ypos += (self._alert_messages['hull breach'].get_size()[1]
689 + self.ALERT_SPACING)
690 if self.game.scenes['bridge'].get_data('ai status') == 'looping':
691 self._background.blit(self._alert_messages['ai looping'],
692 (xpos, ypos))
644 ypos += (self._alert_messages['ai looping'].get_size()[1] 693 ypos += (self._alert_messages['ai looping'].get_size()[1]
645 + self.ALERT_SPACING) 694 + self.ALERT_SPACING)
646 if self.state.scenes['bridge'].get_data('ai status') == 'dead': 695 if self.game.scenes['bridge'].get_data('ai status') == 'dead':
647 surface.blit(self._alert_messages['ai offline'], (xpos, ypos)) 696 self._background.blit(self._alert_messages['ai offline'],
697 (xpos, ypos))
648 ypos += (self._alert_messages['ai offline'].get_size()[1] 698 ypos += (self._alert_messages['ai offline'].get_size()[1]
649 + self.ALERT_SPACING) 699 + self.ALERT_SPACING)
650 if not self.state.scenes['engine'].get_data('engine online'): 700 if not self.game.scenes['engine'].get_data('engine online'):
651 surface.blit(self._alert_messages['engine offline'], (xpos, ypos)) 701 self._background.blit(self._alert_messages['engine offline'],
702 (xpos, ypos))
652 ypos += (self._alert_messages['engine offline'].get_size()[1] 703 ypos += (self._alert_messages['engine offline'].get_size()[1]
653 + self.ALERT_SPACING) 704 + self.ALERT_SPACING)
654 if (self.state.scenes['mess'].get_data('life support status') 705 if (self.game.scenes['mess'].get_data('life support status')
655 == 'broken'): 706 == 'broken'):
656 surface.blit(self._alert_messages['life support'], (xpos, ypos)) 707 self._background.blit(self._alert_messages['life support'],
708 (xpos, ypos))
657 ypos += (self._alert_messages['life support'].get_size()[1] 709 ypos += (self._alert_messages['life support'].get_size()[1]
658 + self.ALERT_SPACING) 710 + self.ALERT_SPACING)
659 if (self.state.scenes['mess'].get_data('life support status') 711 if (self.game.scenes['mess'].get_data('life support status')
660 == 'replaced'): 712 == 'replaced'):
661 surface.blit(self._alert_messages['life support partial'], 713 self._background.blit(self._alert_messages['life support partial'],
662 (xpos, ypos)) 714 (xpos, ypos))
663 ypos += (self._alert_messages['life support partial'].get_size()[1] 715 ypos += (self._alert_messages['life support partial'].get_size()[1]
664 + self.ALERT_SPACING) 716 + self.ALERT_SPACING)
665 717
666 def draw_things(self, surface):
667 if self.get_data('tab') == 'alert':
668 self._draw_alerts(surface)
669 super(BridgeCompDetail, self).draw_things(surface)
670
671 718
672 SCENES = [Bridge] 719 SCENES = [Bridge]
673 DETAIL_VIEWS = [ChairDetail, BridgeCompDetail] 720 DETAIL_VIEWS = [ChairDetail, BridgeCompDetail]