def __init__(self, player: StreamPlayerAbstract, snd_obj: Any, name: str): super(SoundPreview, self).__init__() self.sprite_loader = RomSingleton().get_sprite_loader() self.sprite_loader_os = pge.SpriteLoaderOS( base_path_os="data_permanent/sprites") self.font_loader = RomSingleton().get_font_loader() self.now_playing_text = pge.Text( position=[0, -10], center=[pge.Alignment.CENTER, pge.Alignment.BOTTOM], scale=[0.7, 0.7]) self.font_loader.load("font_event", 12, self.now_playing_text) self.now_playing_text.text = "Now playing:" self.track_name = pge.Text( position=[0, 10], center=[pge.Alignment.CENTER, pge.Alignment.TOP]) self.font_loader.load("font_event", 12, self.track_name) self.track_name.text = name.replace("\\", "/").split("/")[-1] self.explanation_text = pge.Text(position=[0, -50]) self.font_loader.load("font_event", 12, self.explanation_text) self.explanation_text.text = "Touch the headphones to play" self.play_btn = pge.Button(pressed_counter=0.09) self.sprite_loader_os.load("headphones_play.png", self.play_btn, sprite_sheet=True, convert_alpha=False) self.play_btn.color_key = pg.Color(0, 255, 0) self.volume_slider = pge.Slider(min_value=0, max_value=1, start_value=0.5) self.sprite_loader_os.load("slider_main.png", self.volume_slider, sprite_sheet=False) self.sprite_loader_os.load("slider_ball.png", self.volume_slider.child, sprite_sheet=False) self.volume_slider.center = [ pge.Alignment.CENTER, pge.Alignment.BOTTOM ] self.volume_slider.position[1] = 192 // 2 - 20 self.player: StreamPlayerAbstract = player self.player.set_volume(0.5) self.snd_obj: Any = snd_obj self.playing = False if self.check_playable(): self.explanation_text.text = "Touch the headphones to play" self.play_btn.set_tag("OFF") else: self.explanation_text.text = "Missing dependencies" self.play_btn.set_tag("CAN'T BE PLAYED")
def __init__(self, event: Event): super(EventPlayer, self).__init__() self.event = event self.current_command = 0 self.next_voice = -1 self.next_dialogue_sfx = -1 self.sprite_loader = RomSingleton().get_sprite_loader() self.font_loader = RomSingleton().get_font_loader() self.top_bg = EventBG("top") self.sprite_loader.load( f"data_lt2/bg/event/sub{self.event.map_top_id}.arc", self.top_bg.bg, sprite_sheet=False) self.top_bg.fade(2, None, True) self.top_bg.set_opacity(0) self.btm_bg = EventBG("btm") self.sprite_loader.load( f"data_lt2/bg/map/main{self.event.map_bottom_id}.arc", self.btm_bg.bg, sprite_sheet=False) self.btm_bg.set_opacity(120) self.btm_bg.fade(2, None, True) self.waiter = EventWaiter() self.event_sound = EventSound() self.characters: List[Optional[EventCharacter]] = [None] * 8 for i in range(8): if self.event.characters[i] == 0: continue char_id = self.event.characters[i] slot = self.event.characters_pos[i] anim = self.event.characters_anim_index[i] visibility = self.event.characters_shown[i] char = EventCharacter(char_id, slot, anim, visibility, self.sprite_loader) self.characters[i] = char self.dialogue = EventDialogue( self, position=[0, 192 // 2 + 3], center=[pge.Alignment.CENTER, pge.Alignment.BOTTOM]) self.sprite_loader.load("data_lt2/ani/event/twindow.ani", self.dialogue) self.dialogue.init_text(self.font_loader) self.inp = pge.Input() self.wait_tap = False self.run_events_until_busy()
def open_rom(self, rom: Union[NintendoDSRom, BinaryIO, bytes, str, ndspy.rom.NintendoDSRom]): rom_last_filename = self.rom_last_filename if isinstance(rom, str): # Filename rom_last_filename = rom rom = NintendoDSRom.fromFile(rom) elif isinstance(rom, BinaryIO): # File rom = NintendoDSRom(rom.read()) elif isinstance(rom, bytes): # Raw bytes rom = NintendoDSRom(rom) elif isinstance(rom, ndspy.rom.NintendoDSRom): rom = NintendoDSRom(rom.save()) elif isinstance(rom, NintendoDSRom): rom = rom # Load language from arm9 if rom.name == b"LAYTON2": arm9 = rom.loadArm9() lang_address = 0x02000d3c - arm9.ramAddress lang_id = rom.arm9[lang_address] lang_table = ["jp", "en", "sp", "fr", "it", "ge", "du", "ko", "ch"] try: conf.LANG = lang_table[lang_id] except IndexError: # US version? # TODO: Figure out how to read it properly conf.LANG = "en" print(f"Game language: {conf.LANG}") if conf.LANG == "jp": error_dialog = wx.MessageDialog( self, "Japanese is not currently supported", style=wx.ICON_ERROR | wx.OK) error_dialog.ShowModal() return else: warning_game_dialog = wx.MessageDialog( self, "Warning: LaytonEditor is specifically made to edit " "Layton 2, and support with other games is not guaranteed.", style=wx.ICON_WARNING | wx.OK) warning_game_dialog.ShowModal() conf.LANG = "en" # After checking language self.rom = rom self.rom_last_filename = rom_last_filename RomSingleton(rom=self.rom) # Only open the main filesystem page. self.le_editor_pages.DeleteAllPages() menus_to_remove = [] for menu in self.le_menu.Menus: if menu[1] != "File": menus_to_remove.append(menu[1]) for menu_to_remove in menus_to_remove: self.remove_menu(menu_to_remove) self.open_filesystem_page("Rom FS")
class SoundPreview(TwoScreenRenderer): def __init__(self, player: StreamPlayerAbstract, snd_obj: Any, name: str): super(SoundPreview, self).__init__() self.sprite_loader = RomSingleton().get_sprite_loader() self.sprite_loader_os = pge.SpriteLoaderOS( base_path_os="data_permanent/sprites") self.font_loader = RomSingleton().get_font_loader() self.now_playing_text = pge.Text( position=[0, -10], center=[pge.Alignment.CENTER, pge.Alignment.BOTTOM], scale=[0.7, 0.7]) self.font_loader.load("font_event", 12, self.now_playing_text) self.now_playing_text.text = "Now playing:" self.track_name = pge.Text( position=[0, 10], center=[pge.Alignment.CENTER, pge.Alignment.TOP]) self.font_loader.load("font_event", 12, self.track_name) self.track_name.text = name.replace("\\", "/").split("/")[-1] self.explanation_text = pge.Text(position=[0, -50]) self.font_loader.load("font_event", 12, self.explanation_text) self.explanation_text.text = "Touch the headphones to play" self.play_btn = pge.Button(pressed_counter=0.09) self.sprite_loader_os.load("headphones_play.png", self.play_btn, sprite_sheet=True, convert_alpha=False) self.play_btn.color_key = pg.Color(0, 255, 0) self.volume_slider = pge.Slider(min_value=0, max_value=1, start_value=0.5) self.sprite_loader_os.load("slider_main.png", self.volume_slider, sprite_sheet=False) self.sprite_loader_os.load("slider_ball.png", self.volume_slider.child, sprite_sheet=False) self.volume_slider.center = [ pge.Alignment.CENTER, pge.Alignment.BOTTOM ] self.volume_slider.position[1] = 192 // 2 - 20 self.player: StreamPlayerAbstract = player self.player.set_volume(0.5) self.snd_obj: Any = snd_obj self.playing = False if self.check_playable(): self.explanation_text.text = "Touch the headphones to play" self.play_btn.set_tag("OFF") else: self.explanation_text.text = "Missing dependencies" self.play_btn.set_tag("CAN'T BE PLAYED") def unload(self): super(SoundPreview, self).unload() self.now_playing_text.unload() self.track_name.unload() self.explanation_text.unload() self.play_btn.unload() self.player.stop() def check_playable(self): return self.player.get_playable() def toggle_sound(self): if not self.check_playable(): return if self.playing: self.stop_sound() else: self.start_sound() def start_sound(self): self.play_btn.set_tag("ON") if self.snd_obj and not self.playing: self.playing = True self.player.start_sound(self.snd_obj) def stop_sound(self): self.play_btn.set_tag("OFF") self.playing = False self.player.stop() def update(self, dt: float): if self.play_btn.pressed(self.btm_camera, dt): self.toggle_sound() self.play_btn.animate(dt) self.player.update_(dt) def draw(self): self.top_camera.surf.fill((40, 40, 40)) self.now_playing_text.draw(self.top_camera) self.track_name.draw(self.top_camera) self.play_btn.draw(self.btm_camera) self.explanation_text.draw(self.btm_camera) slider_value, changed = self.volume_slider.get_value(self.btm_camera) if changed: self.player.set_volume(slider_value) self.volume_slider.draw(self.btm_camera)
def __init__(self, place: Place): super(PlacePreview, self).__init__() self.place = place self.sprite_loader = RomSingleton().get_sprite_loader() self.font_loader = RomSingleton().get_font_loader() self.inp = pge.Input() self.top_bg = pge.Sprite() self.sprite_loader.load( f"data_lt2/bg/map/map{self.place.map_image_index}", self.top_bg, sprite_sheet=False, convert_alpha=False) self.btm_bg = pge.Sprite() self.sprite_loader.load( f"data_lt2/bg/map/main{self.place.background_image_index}", self.btm_bg, sprite_sheet=False, convert_alpha=False) self.map_icon = pge.Sprite( position=[ self.place.map_x - 256 // 2, self.place.map_y - 192 // 2 ], center=[pge.Alignment.LEFT, pge.Alignment.TOP]) self.sprite_loader.load(f"data_lt2/ani/map/mapicon.arj", self.map_icon, sprite_sheet=True, convert_alpha=False) self.move_mode = False self.move_button = pge.Button( position=[256 // 2 - 3, 192 // 2 - 3], center=[pge.Alignment.RIGHT, pge.Alignment.BOTTOM], pressed_tag="on", not_pressed_tag="off") self.sprite_loader.load(f"data_lt2/ani/map/movemode.arc", self.move_button, sprite_sheet=True, convert_alpha=False) self.bgm = SMDLStreamPlayer() self.sprites = [] self.objects = [] self.exits = [] for sprite_obj in self.place.sprites: if sprite_obj.filename == "": continue sprite = pge.Sprite( position=[sprite_obj.x - 256 // 2, sprite_obj.y - 192 // 2], center=[pge.Alignment.LEFT, pge.Alignment.TOP], color_key=pg.Color(0, 255, 0)) self.sprite_loader.load( f"data_lt2/ani/bgani/{sprite_obj.filename}", sprite, sprite_sheet=True, convert_alpha=False) sprite.set_tag("gfx") self.sprites.append(sprite) for object_obj in self.place.objects: if object_obj.width <= 0: continue obj = pge.Sprite( position=[object_obj.x - 256 // 2, object_obj.y - 192 // 2], center=[pge.Alignment.LEFT, pge.Alignment.TOP], color_key=pg.Color(0, 255, 0)) if object_obj.character_index != 0: self.sprite_loader.load( f"data_lt2/ani/eventobj/obj_{object_obj.character_index}.arc", obj, sprite_sheet=True, convert_alpha=False) obj.set_tag("gfx") self.objects.append(obj) for exit_obj in self.place.exits: if exit_obj.width <= 0: continue exit_ = FadeInOutBtn( position=[exit_obj.x - 256 // 2, exit_obj.y - 192 // 2], center=[pge.Alignment.LEFT, pge.Alignment.TOP], color_key=pg.Color(0, 255, 0), pressed_tag="gfx2", not_pressed_tag="gfx") self.sprite_loader.load( f"data_lt2/ani/map/exit_{exit_obj.image_index}.arc", exit_, sprite_sheet=True, convert_alpha=False) self.exits.append(exit_)
def __init__(self, puzzle_data: pzd.Puzzle): super(PuzzlePlayer, self).__init__() self.hints_used = 0 self.selected_hint = 0 self.text_pos = 0 self.between_letters = 0.017 self.current_between_letters = 0.0 self.on_hints = False self.puzzle_data = puzzle_data self.inp = pge.Input() self.sprite_loader: pge.SpriteLoader = RomSingleton( ).get_sprite_loader() self.font_loader: pge.FontLoader = RomSingleton().get_font_loader() self.top_bg = pge.Sprite() self.sprite_loader.load( f"data_lt2/bg/nazo/system/nazo_text{puzzle_data.bg_top_id}.arc", self.top_bg, sprite_sheet=False) self.btm_bg = pge.Sprite() if not puzzle_data.bg_lang: self.sprite_loader.load( f"data_lt2/bg/nazo/q{puzzle_data.internal_id}.arc", self.btm_bg, sprite_sheet=False) else: self.sprite_loader.load( f"data_lt2/bg/nazo/?/q{puzzle_data.internal_id}.arc", self.btm_bg, sprite_sheet=False) self.top_text = pge.Text( position=[-256 // 2 + 8, -192 // 2 + 23], center=[pge.Alignment.LEFT, pge.Alignment.TOP], color=pg.Color(0, 0, 0), line_spacing=2) self.font_loader.load("fontq", 10, self.top_text) self.header_top_left = [] for i in range(4): header_item = pge.Sprite( center=[pge.Alignment.TOP, pge.Alignment.LEFT]) self.sprite_loader.load( f"data_lt2/ani/nazo/system/?/nazo_text.arc", header_item, sprite_sheet=True) if i == 0: header_item.set_tag("nazo") header_item.position = [-256 // 2 + 5, -192 // 2 + 4] else: i -= 1 p_num = puzzle_data.number for a in range(2 - i): p_num //= 10 header_item.set_tag(str(p_num % 10)) header_item.position = [-256 // 2 + 23 + i * 7, -192 // 2 + 5] self.header_top_left.append(header_item) self.hint_bg = pge.Sprite() btn_off = "off" btn_on = "on" current_y = -192 // 2 self.hints_btn = pge.Button( center=[pge.Alignment.RIGHT, pge.Alignment.TOP], position=[256 // 2, current_y], not_pressed_tag="0_off", pressed_tag="0_on") self.sprite_loader.load("data_lt2/ani/system/btn/?/hint.arc", self.hints_btn, sprite_sheet=True) current_y += self.hints_btn.get_world_rect().h self.quit_btn = pge.Button( center=[pge.Alignment.RIGHT, pge.Alignment.TOP], position=[256 // 2, current_y], not_pressed_tag=btn_off, pressed_tag=btn_on) self.sprite_loader.load("data_lt2/ani/system/btn/?/atode.arc", self.quit_btn, sprite_sheet=True) current_y += self.quit_btn.get_world_rect().h self.memo_btn = pge.Button( center=[pge.Alignment.RIGHT, pge.Alignment.TOP], position=[256 // 2, current_y], not_pressed_tag=btn_off, pressed_tag=btn_on) self.sprite_loader.load("data_lt2/ani/system/btn/?/memo.arc", self.memo_btn, sprite_sheet=True) self.submit_btn = pge.Button( center=[pge.Alignment.RIGHT, pge.Alignment.BOTTOM], position=[256 // 2, 192 // 2], not_pressed_tag=btn_off, pressed_tag=btn_on) self.sprite_loader.load("data_lt2/ani/system/btn/?/hantei.arc", self.submit_btn, sprite_sheet=True) self.hint_back = pge.Button( position=[256 // 2, -192 // 2], center=[pge.Alignment.RIGHT, pge.Alignment.TOP], not_pressed_tag=btn_off, pressed_tag=btn_on) self.sprite_loader.load("data_lt2/ani/system/btn/?/modoru_memo.arc", self.hint_back, sprite_sheet=True) self.hint_unlock = pge.Button( position=[-80, 40], center=[pge.Alignment.LEFT, pge.Alignment.TOP], not_pressed_tag=btn_off, pressed_tag=btn_on) self.sprite_loader.load("data_lt2/ani/system/btn/?/yes.arc", self.hint_unlock, sprite_sheet=True) self.hint_no_unlock = pge.Button( position=[80, 40], center=[pge.Alignment.RIGHT, pge.Alignment.TOP], not_pressed_tag=btn_off, pressed_tag=btn_on) self.sprite_loader.load("data_lt2/ani/system/btn/?/no.arc", self.hint_no_unlock, sprite_sheet=True) self.hint_text = pge.Text( position=[-256 // 2 + 20, -192 // 2 + 42], center=[pge.Alignment.LEFT, pge.Alignment.TOP], color=pg.Color(0, 0, 0)) self.font_loader.load("fontq", 10, self.hint_text) self.hint_selected: List[pge.Button] = [] current_x = -256 // 2 + 8 for i in range(3): hint_select = pge.Button( position=[current_x, -192 // 2 + 4], center=[pge.Alignment.LEFT, pge.Alignment.TOP], not_pressed_tag="OFF", pressed_tag="ON") hint_select.visible = False self.sprite_loader.load( f"data_lt2/ani/nazo/system/?/hint{i + 1}.arc", hint_select, sprite_sheet=True) current_x += hint_select.get_world_rect().w + 1 self.hint_selected.append(hint_select) self.view_hint(self.progress_hints(set_hint=0)) smd, presets = load_smd("data_lt2/sound/BG_035.SMD") self.puzzle_bg_music = SMDLStreamPlayer() self.puzzle_bg_music.set_preset_dict(presets) self.puzzle_bg_music.start_sound(smd, loops=-1)
class EventPlayer(TwoScreenRenderer): def __init__(self, event: Event): super(EventPlayer, self).__init__() self.event = event self.current_command = 0 self.next_voice = -1 self.next_dialogue_sfx = -1 self.sprite_loader = RomSingleton().get_sprite_loader() self.font_loader = RomSingleton().get_font_loader() self.top_bg = EventBG("top") self.sprite_loader.load( f"data_lt2/bg/event/sub{self.event.map_top_id}.arc", self.top_bg.bg, sprite_sheet=False) self.top_bg.fade(2, None, True) self.top_bg.set_opacity(0) self.btm_bg = EventBG("btm") self.sprite_loader.load( f"data_lt2/bg/map/main{self.event.map_bottom_id}.arc", self.btm_bg.bg, sprite_sheet=False) self.btm_bg.set_opacity(120) self.btm_bg.fade(2, None, True) self.waiter = EventWaiter() self.event_sound = EventSound() self.characters: List[Optional[EventCharacter]] = [None] * 8 for i in range(8): if self.event.characters[i] == 0: continue char_id = self.event.characters[i] slot = self.event.characters_pos[i] anim = self.event.characters_anim_index[i] visibility = self.event.characters_shown[i] char = EventCharacter(char_id, slot, anim, visibility, self.sprite_loader) self.characters[i] = char self.dialogue = EventDialogue( self, position=[0, 192 // 2 + 3], center=[pge.Alignment.CENTER, pge.Alignment.BOTTOM]) self.sprite_loader.load("data_lt2/ani/event/twindow.ani", self.dialogue) self.dialogue.init_text(self.font_loader) self.inp = pge.Input() self.wait_tap = False self.run_events_until_busy() def run_events_until_busy(self): while True: if self.current_command >= len(self.event.gds.commands): return command = self.event.gds.commands[self.current_command] self.current_command += 1 self.execute_gds_command(command) if self.is_busy(): return def execute_gds_command(self, command: gds.GDSCommand): fade_out = 1 fade_in = 2 if command.command == 0x2: self.top_bg.fade(fade_in, None, False) self.btm_bg.fade(fade_in, None, False) elif command.command == 0x3: self.top_bg.fade(fade_out, None, False) self.btm_bg.fade(fade_out, None, False) elif command.command == 0x4: if len(command.params) == 0: return dialogue_gds = self.event.get_text(command.params[0]) if len(dialogue_gds.params) != 5: return character = None for char in self.characters: if char is None: continue if char.get_char_id() == dialogue_gds.params[0]: character = char break self.dialogue.start_dialogue(character, dialogue_gds.params[1], dialogue_gds.params[4], self.next_voice, self.next_dialogue_sfx, self.sprite_loader) self.next_voice = -1 self.next_dialogue_sfx = -1 elif command.command == 0x21: bg_path = command.params[0] self.sprite_loader.load(f"data_lt2/bg/{bg_path}", self.btm_bg.bg, sprite_sheet=False) self.btm_bg.set_opacity(0) elif command.command == 0x22: bg_path = command.params[0] self.sprite_loader.load(f"data_lt2/bg/{bg_path}", self.top_bg.bg, sprite_sheet=False) self.top_bg.set_opacity(0) elif command.command == 0x2a: self.characters[command.params[0]].show() elif command.command == 0x2b: self.characters[command.params[0]].hide() elif command.command == 0x2c: # Still not clue about why it works like this if command.params[0] < 8: self.characters[command.params[0]].set_visibility( command.params[1] > 0) elif command.command == 0x30: self.characters[command.params[0]].set_slot(command.params[1]) elif command.command == 0x31: self.waiter.wait(command.params[0]) elif command.command == 0x32: self.btm_bg.fade(fade_in, None, False) elif command.command == 0x33: self.btm_bg.fade(fade_out, None, False) elif command.command == 0x37: self.btm_bg.set_opacity(command.params[3]) elif command.command == 0x3f: character = None for char in self.characters: if char is None: continue if char.get_char_id() == command.params[0]: character = char break if character: character.set_anim(command.params[1]) elif command.command == 0x5c: self.next_voice = command.params[0] elif command.command == 0x5d: self.event_sound.play_sadl( f"data_lt2/stream/ST_{str(command.params[0]).zfill(3)}.SAD") elif command.command == 0x62: self.event_sound.play_smdl( f"data_lt2/sound/BG_{str(command.params[0]).zfill(3)}.SMD") elif command.command == 0x69: self.wait_tap = True elif command.command == 0x6a: self.btm_bg.shake() elif command.command == 0x71: # Something about mysteries -> hides all character for char in self.characters: if char: char.hide() elif command.command == 0x72: self.top_bg.fade(fade_out, command.params[0], False) self.btm_bg.fade(fade_out, command.params[0], False) elif command.command == 0x80: self.top_bg.fade(fade_in, command.params[0], False) self.btm_bg.fade(fade_in, command.params[0], False) elif command.command == 0x87: self.top_bg.fade(fade_out, command.params[0], False) elif command.command == 0x88: self.top_bg.fade(fade_in, command.params[0], False) elif command.command == 0x8a: self.event_sound.fade(False, command.params[1]) elif command.command == 0x8b: self.event_sound.fade(True, command.params[0]) elif command.command == 0x99: self.next_dialogue_sfx = command.params[0] else: print( f"[EventPlayer] Command {hex(command.command)} not recognised (skipped). " ) def execute_str_command(self, command): print(command) command_split = command.split(" ") if command_split[0] == "setani": try: int(command_split[1]) except ValueError: return character = None for char in self.characters: char: EventCharacter if char.get_char_id() == int(command_split[1]): character = char break if character: character.set_anim(command_split[2].replace("_", " ")) def update(self, dt: float): for character in self.characters: if character is not None: character.update_fade(dt) self.waiter.update_(dt) self.event_sound.update_(dt) self.top_bg.update_(dt) self.btm_bg.update_(dt) self.dialogue.interact(self.btm_camera, dt) for character in self.characters: if character: character.animate(dt) if self.wait_tap: if self.inp.get_mouse_down(1): self.wait_tap = False if not self.is_busy(): self.run_events_until_busy() def draw(self): self.top_bg.draw_back(self.top_camera) self.top_bg.draw_front(self.top_camera) self.btm_bg.draw_back(self.btm_camera) for character in self.characters: if character: character.draw(self.btm_camera) self.dialogue.draw(self.btm_camera) self.btm_bg.draw_front(self.btm_camera) def unload(self): self.top_bg.unload() self.btm_bg.unload() for character in self.characters: if character: character.unload() self.dialogue.unload() self.event_sound.stop_smdl() self.event_sound.stop_sadl() def is_busy(self): for character in self.characters: if character is not None: if character.busy(): return True return self.top_bg.busy() or self.btm_bg.busy() or self.waiter.busy( ) or self.dialogue.busy() or self.wait_tap