def read(data: ScnDataReader): color_table_name = data.string_fixed(30, debug='color_table_name') color_table_id = data.uint16(debug='color_table_id') drs_res = data.uint16(debug='color_table_drs_res') # All blanks? minimap_color = data.uint8(debug='color_table_minimap_color') # Possibly a minimap color? color_table_type = data.uint8(debug='color_table_type') # All 1's except the last one, which is 2. return ColorTable(color_table_name, color_table_id, drs_res, minimap_color, color_table_type)
def read(data: ScnDataReader): field1 = data.string16(debug='player_name_repeated') field2 = data.float32(debug='unknown field 1') field3 = data.float32(debug='unknown field 2') field4 = data.uint16(debug='unknown field 3') field5 = data.uint16(debug='unknown field 4') field6 = data.uint8(debug='unknown field 5') field7 = data.uint16(debug='unknown field 6') field8 = [] for j in range(0, 9): something = data.uint8(debug='unknown field {}'.format(j)) field8.append(something) field9 = [] for j in range(0, 9): something = data.uint32(debug='unknown field {}'.format(j)) field9.append(something) field10 = data.float32(debug="unknown field") # 1.00 field11 = data.float32( debug="unknown field" ) # only seen 0. guess this could be float as well ? field12 = [] for j in range( 0, 9 ): # all 0's. guessing it could hold another list of 9 values? something = data.uint8(debug='unknown field {}'.format(j)) field12.append(something) return UnknownPlayerDataStructure(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10, field11, field12)
def load(data: ScnDataReader) -> List[Civilization]: """ Read all civilizations from here """ data.mark("civilizations") num_civs = data.int16(debug='num_civs') for i in range(0, num_civs): data.uint8(debug='civ_type {}'.format(i)) data.string_fixed(size=20, debug='civ_name {}'.format(i)) civ_num_attributes = data.uint16( debug='civ_num_attributes {}'.format(i)) civ_effect = data.int16(debug='civ_effect {}'.format(i)) # civ_bonus_effect = data.int16(debug='civ_bonus_effect {}'.format(i)) # Might not exist in AOE1 dat. civ_attributes = [ data.float32(debug='civ_attribute {} {}'.format(i, x)) for x in range(0, civ_num_attributes) ] civ_icon_set = data.uint8(debug='civ_icon_set {}'.format(i)) civ_num_units = data.uint16(debug='civ_num_units {}'.format(i)) civ_unit_available = [ data.boolean32(debug='civ_unit_available {} {}'.format(i, x)) for x in range(0, civ_num_units) ] for j in range(0, civ_num_units): if not civ_unit_available[j]: continue read_unit(data) return []
def read(data: ScnDataReader): id = data.uint32(debug='random_map_id') terrain_type = data.uint8(debug='random_map_terrain_type') _padding1 = data.uint16(debug='random_map_padding1') _padding2 = data.uint8(debug='random_map_padding2') spacing = data.int32(debug='random_map_spacing') base_square_radius = data.int32(debug='random_map_base_square_radius') zone = data.int8(debug='random_map_zone') placement_type = data.int8(debug='random_map_placement_type') _padding3 = data.uint16(debug='random_map_padding3') land_x = data.int32(debug='random_map_land_x') land_y = data.int32(debug='random_map_land_y') amount_of_land_used_percent = data.int8(debug='random_map_amount_of_land_used_percent') land_by_player_flag = data.int8(debug='random_map_land_by_player_flag') _padding4 = data.uint16(debug='random_map_padding4') radius = data.int32(debug='random_map_radius') fade = data.int32(debug='random_map_fade') clumpiness_factor = data.int32(debug='random_map_clumpiness_factor') return RandomMapLand( id, terrain_type, spacing, base_square_radius, zone, placement_type, land_x, land_y, amount_of_land_used_percent, land_by_player_flag, radius, fade, clumpiness_factor )
def load(data: ScnDataReader): # Terrain data.mark(name='terrain') # num_terrains_override = num_terrains num_terrains_override = 32 for i in range(0, num_terrains_override): data.boolean8(debug='terrain_enabled {}'.format(i)) data.uint8(debug='terrain_random {}'.format(i)) # always 0? data.string_fixed(size=13, debug='terrain_name {}'.format(i)) data.string_fixed(size=13, debug='terrain_texture_name {}'.format( i)) # Maybe read as int and test agains -1? data.int32(debug='terrain_slp_id {}'.format(i)) data.int32(debug='terrain_slp_pointer {}'.format(i)) data.int32(debug='terrain_sound_id {}'.format(i)) data.uint8(debug='terrain_minimap_color_high {}'.format( i)) # These colors are off-by-one compared with AGE. data.uint8(debug='terrain_minimap_color_medium {}'.format(i)) data.uint8(debug='terrain_minimap_color_low {}'.format(i)) data.uint8(debug='terrain_minimap_color_cliff_lt {}'.format(i)) data.uint8(debug='terrain_minimap_color_cliff_rt {}'.format(i)) data.int8(debug='terrain_passable_id {}'.format(i)) data.int8(debug='terrain_impassable_id {}'.format(i)) # Animation data.boolean8(debug='terrain_animation_enabled {}'.format(i)) data.int16(debug='terrain_anim_num_frames {}'.format(i)) data.int16(debug='terrain_anim_num_pause_frames {}'.format(i)) data.float32(debug='terrain_anim_frame_interval {}'.format(i)) data.float32(debug='terrain_anim_replay_delay {}'.format(i)) data.int16(debug='terrain_anim_frame {}'.format(i)) data.int16(debug='terrain_anim_draw_frame {}'.format(i)) data.float32(debug='terrain_anim_animate_last {}'.format(i)) data.boolean8(debug='terrain_anim_frame_changed {}'.format(i)) data.boolean8(debug='terrain_anim_drawn {}'.format(i)) # Elevation sprites for j in range(0, 19): data.uint16(debug="terrain_elevation_sprite_frames {} {}".format( i, j)) # frames data.uint16(debug="terrain_elevation_sprite_facets {} {}".format( i, j)) # facets data.uint16(debug="terrain_elevation_sprite_frame_id {} {}".format( i, j)) # frame_id data.int16(debug="terrain_to_draw {}".format(i)) data.uint16(debug="terrain_rows {}".format(i)) data.uint16(debug="terrain_cols {}".format(i)) # Borders for j in range(0, num_terrains_override): data.uint16(debug="terrain_border {} {}".format(i, j)) # Objects for j in range(0, 30): data.uint16(debug="terrain_object_id {} {}".format(i, j)) for j in range(0, 30): data.int16(debug="terrain_density {} {}".format(i, j)) for j in range(0, 30): data.int8(debug="terrain_placement_flag {} {}".format( i, j)) # 0 for random, 1 for central data.uint16(debug="terrain_object_count {}".format(i)) data.uint16(debug="padding {}".format(i)) return []
def read(data: ScnDataReader): data.boolean8(debug="border_enabled") data.boolean8(debug="border_random") data.string_fixed(size=13, debug='border_name') data.string_fixed(size=13, debug='border_texture_name') # Maybe read as int and test agains -1? data.int32(debug='border_slp_id') data.int32(debug='border_slp_pointer') data.int32(debug='border_sound_id') data.uint8(debug='border_minimap_color_high') data.uint8(debug='border_minimap_color_medium') data.uint8(debug='border_minimap_color_low') # Same as terrain animation data.boolean8(debug='border_manimation_enabled') data.int16(debug='border_anim_num_frames') data.int16(debug='border_anim_num_pause_frames') data.float32(debug='border_anim_frame_interval') data.float32(debug='border_anim_replay_delay') data.int16(debug='border_anim_frame') data.int16(debug='border_anim_draw_frame') data.float32(debug='border_anim_animate_last') data.boolean8(debug='border_anim_frame_changed') data.boolean8(debug='border_anim_drawn') for j in range(0, 19): for k in range(0, 12): data.uint16(debug="border_elevation_sprite_frames {} {}".format(j, k)) # frames data.uint16(debug="border_elevation_sprite_facets {} {}".format(j, k)) # facets data.uint16(debug="border_elevation_sprite_rame_id {} {}".format(j, k)) # frame_id data.int8(debug='border_draw_tile') data.uint8(debug='padding') data.int16(debug='border_underlay_terrain') data.int16(debug='border_style') return TerrainBorder()
def debug_count_until(byte: int, data: ScnDataReader): for i in range(0, 500): if data.uint8() == byte: print("Need to skip {} bytes".format(i)) return logging.info("Value not found") exit(1)
def read_unit(data: ScnDataReader): # next data structure to read depends on the unit type! unit_type = data.uint8(debug='unit type'.format()) if unit_type == 10: # base read_decorative_unit(data) elif unit_type == 15: # tree raise Exception("Not implemented") elif unit_type == 20: # animated read_animated_unit(data) elif unit_type == 25: # doppleganger read_doppleganger_unit(data) elif unit_type == 30: # moving read_moving_unit(data) elif unit_type == 40: # action read_action_unit(data) elif unit_type == 50: # base raise Exception("Not implemented") elif unit_type == 60: # missile read_missile_unit(data) elif unit_type == 70: read_combat_unit(data) elif unit_type == 80: read_building_unit(data) elif unit_type == 90: read_tree(data) else: raise Exception("Dont know how to read unit type {}".format(unit_type))
def read(data: ScnDataReader): required_techs = [ data.int16(debug='required_tech1'), data.int16(debug='required_tech2'), data.int16(debug='required_tech3'), data.int16(debug='required_tech4') ] costs = [TechnologyCost.read(data) for _ in range(0, 3)] min_required_techs = data.int16(debug='min_required_techs') research_location = data.int16(debug='research_location') langauge_file_name = data.int16(debug='langauge_file_name') language_file_desc = data.int16(debug='language_file_desc') research_time = data.int16(debug='research_time') effect = data.int16(debug='effect') type = data.int16(debug='type') icon = data.int16(debug='icon') button = data.uint8(debug='button') lang_file_help = data.int32(debug='lang_file_help') lang_file_tech_tree = data.int32(debug='lang_file_tech_tree') hotkey = data.uint32(debug='hotkey') tech_name_len = data.uint16(debug='name_len') name = data.string_fixed(size=tech_name_len, debug='name') return Technology(required_techs, costs, min_required_techs, research_location, langauge_file_name, language_file_desc, research_time, effect, type, icon, button, lang_file_help, lang_file_tech_tree, hotkey, name)
def read(data: ScnDataReader): effect_comamnd_type = data.uint8() effect_params = ( data.int16(), data.int16(), data.int16(), data.float32() ) return EffectCommand(effect_comamnd_type, effect_params)
def read_classic(data: ScnDataReader, file_version: float): return ScenarioObject( (data.float32(), data.float32(), data.float32()), data.uint32(), data.uint16(), data.uint8(), data.float32(), # Not used in AOE1 -1 if file_version < 1.15 else data.uint16(), -1 if file_version < 1.13 else data.uint32())
def read(data: ScnDataReader, sprite_id): sprite_name = data.string_fixed(21, debug='sprite_name') sprite_filename = data.string_fixed(13, debug='sprite_filename') sprite_slp_id = data.uint32(debug='sprite_slp_id') sprite_is_loaded = data.boolean8(debug='sprite_is_loaded') sprite_color_flag = data.boolean8(debug='sprite_color_flag') sprite_layer = data.uint8(debug='sprite_layer') sprite_color_table = data.int16(debug='sprite_color_table') sprite_transparent_selection = data.boolean8( debug='sprite_transparent_selection') sprite_bounding_box = ( data.int16(), # X1 data.int16(), # Y1 data.int16(), # X2 data.int16()) # Y2 sprite_num_deltas = data.uint16(debug='sprite_num_deltas') sprite_sound_id = data.int16(debug='sprite_sound_id') attack_sounds_used = data.boolean8() sprite_num_frames = data.uint16() sprite_num_facets = data.uint16() sprite_base_speed = data.float32() sprite_frame_rate = data.float32() sprite_replay_delay = data.float32() sprite_sequence_type = data.uint8() sprite_other_id = data.uint16(debug='sprite_other_id') sprite_mirror_flag = data.uint8() # sprite_other_flag = data.uint8() # Reading 1 byte too far here, one of these must not be in the AOE1 file. sprite_deltas = [ SpriteDelta.read(data) for _ in range(0, sprite_num_deltas) ] facets = [SpriteFacet.read(data) for _ in range(0, sprite_num_facets) ] if attack_sounds_used else [] return Sprite(sprite_id, sprite_name, sprite_filename, sprite_slp_id, sprite_is_loaded, sprite_color_flag, sprite_layer, sprite_color_table, sprite_transparent_selection, sprite_bounding_box, sprite_sound_id, attack_sounds_used, sprite_num_frames, sprite_num_facets, sprite_base_speed, sprite_frame_rate, sprite_replay_delay, sprite_sequence_type, sprite_other_id, sprite_mirror_flag, sprite_deltas, facets)
def read(data: ScnDataReader): return ScnMapTile( data.uint8(), data.uint8(), data.uint8() )
def read_base_unit_props(data: ScnDataReader): data.mark("base unit") unit_name_len = data.uint16(debug='unit_name_len') unit_id = data.int16(debug='unit_id') unit_name_string_id = data.int16(debug='unit_name_string_id') unit_creation_string_id = data.int16(debug='unit_creation_string_id') unit_class = data.int16(debug='unit_class') standing_sprite = data.int16( debug='standing_sprite') # no standing sprite #2 here.. ? dying_sprite = data.int16(debug='dying_sprite') undead_sprite = data.int16(debug='undead_sprite') undead_flag = data.int8(debug='undead_flag') hp = data.uint16(debug='hp') los = data.float32(debug='los') garrison_capacity = data.uint8(debug='garrison_capacity') collision_radius = (data.float32(debug='collision_radius1'), data.float32(debug='collision_radius2'), data.float32(debug='collision_radius3')) unit_train_sound = data.int16(debug='train_sound') # unit_damage_sound = data.int16(debug='damage_sound') unit_death_spawn = data.int16( debug='unit_death_spawn') # no unit_damage_sound here ?? unit_sort_number = data.uint8(debug='unit_sort_number') unit_can_be_built_on = data.uint8(debug='unit_can_be_built_on') unit_button_picture = data.int16(debug='unit_button_picture') unit_hide_in_scenario_editor = data.boolean8( debug='unit_hide_in_scenario_editor') unit_portrait_picture = data.int16(debug='unit_portrait_picture') unit_enabled = data.boolean8( debug='unit_enabled') # no unit_disabled here ?? unit_tile_req = (data.int16(debug='unit_tile_req1'), data.int16(debug='unit_tile_req2') ) # "Placement side terrains" unit_center_tile_req = (data.int16(debug='unit_center_tile_req1'), data.int16(debug='unit_center_tile_req1')) unit_construction_radius = (data.float32( debug='unit_construction_radius1'), data.float32( debug='unit_construction_radius2')) unit_elevation_flag = data.boolean8(debug='unit_elevation_flag') unit_fog_flag = data.boolean8(debug='unit_fog_flag') unit_terrain_restriction_id = data.uint16( debug='unit_terrain_restriction_id') # "terrain tables" unit_movement_type = data.uint8(debug='unit_movement_type') unit_attribute_max_amount = data.uint16( debug='unit_attribute_max_amount') # resource capacity unit_attribute_rot = data.float32(debug='unit_attribute_rot') # decay unit_area_effect_level = data.uint8(debug='unit_area_effect_level') unit_combat_level = data.uint8(debug='unit_combat_level') unit_select_level = data.uint8(debug='unit_select_level') unit_map_draw_level = data.uint8(debug='unit_map_draw_level') unit_level = data.uint8(debug='unit_level') unit_multiple_attribute_mod = data.float32( debug='unit_multiple_attribute_mod') unit_map_color = data.uint8(debug='unit_map_color') unit_help_string_id = data.uint32('unit_help_string_id') unit_help_page_id = data.uint32(debug='unit_help_page_id') unit_hotkey_id = data.uint32(debug='unit_hotkey_id') unit_recyclable = data.boolean8(debug='unit_recyclable') unit_track_as_resource = data.boolean8(debug='unit_track_as_resource') unit_create_doppleganger = data.boolean8(debug='unit_create_doppleganger') unit_resource_group = data.uint8( debug='unit_resource_group') # tree/stone/gold etc unit_occlusion_mask = data.uint8( debug='unit_occlusion_mask') # "hill mode" in AGE unit_obstruction_type = data.uint8( debug='unit_obstruction_type' ) # dropped unit_selection_shape, unit_civilization, unit_attribute_piece # # object flags go here in later versions selection_outline_radius = ( data.float32(debug='selection_outline_radius1'), data.float32(debug='selection_outline_radius2'), data.float32(debug='selection_outline_radius3')) for i in range(0, 3): attribute_res = data.int16(debug='attribute_res {}'.format(i)) attribute_amount = data.float32(debug='attribute_amount {}'.format(i)) attribute_store_mode = data.int8( debug='attribute_store_mode {}'.format(i)) num_damage_sprites = data.uint8(debug='num_damage_sprites') for i in range(0, num_damage_sprites): damage_sprite = data.uint16(debug='damage_sprite {}'.format(i)) damage_percent = data.uint8(debug='damage_percent {}'.format(i)) damage_apply_mode = data.uint8(debug='damage_apply_mode {}'.format(i)) damage_unused = data.uint8(debug='damage_unused {}'.format(i)) unit_selected_sound = data.int16(debug='unit_selected_sound') unit_death_sound = data.int16(debug='unit_death_sound') unit_attack_reaction = data.uint8(debug='unit_attack_reaction') unit_convert_terrain_flag = data.uint8(debug='unit_convert_terrain_flag') unit_name = data.string_fixed(size=unit_name_len, debug='unit_name') data.uint16(debug='unit_copy_id') # dropped unit_copy_id, unit_group return unit_name
def read_de(data: ScnDataReader): version = data.float32(debug='version') for i in range(0, 16): data.uint16(debug='some number here') # 2656 data.string16(debug='player tribe name') if version >= 3.13: # These 16 bytes are not present in some DE scenarios bundled w/ the game, labelled version 3.125. for i in range(0, 16): # Guessing its a string ref, have not checked data.int32(debug="unknown_string_ref for player {}".format(i)) for i in range(0, 16): player_base_props = ScnPlayerBaseProperties.read(data) logging.debug(player_base_props) data.boolean32(debug='conquest maybe') data.float32(debug='probable check field') data.uint8(debug='unknown field') data.uint16(debug='some number here') # 2656 data.string16(debug='scenario_name') data.uint16(debug='some number here') # 2656 data.string16(debug='scenario_instructions') data.uint16(debug='some number here') # 2656 data.string16(debug='history_string') data.uint16(debug='some number here') # 2656 data.string16(debug='victory_string') data.uint16(debug='some number here') # 2656 data.string16(debug='loss_string') data.uint16(debug='some number here') # 2656 data.string16(debug='history_string') data.int32(debug='instructions_string_reference') data.uint16(debug='some_number_here') # 2656 data.string16(debug='instructions_vox') data.int32(debug='hints_string_reference') data.uint16(debug='some_number_here') # 2656 data.string16(debug='hints_vox') data.int32(debug='victory_string_reference') data.uint16(debug='some_number_here') # 2656 data.string16(debug='victory_vox') data.int32(debug='loss_string_reference') data.uint16(debug='some_number_here') # 2656 data.string16(debug='loss_vox') data.int32(debug='history_string_reference') data.uint16(debug='some_number_here') # 2656 data.string16(debug='history_vox') # Not sure if cinematics or per-player personality, AI, city plans etc data.uint16(debug='some_number_here') # 2656 data.string16(debug='unidentified_string 1') # ' <None> ' data.uint16(debug='some_number_here') # 2656 data.string16(debug='unidentified_string 2') # ' <None> ' data.uint16(debug='some_number_here') # 2656 data.string16(debug='unidentified_string 3') # ' <None> ' data.uint16(debug='some_number_here') # 2656 data.string16(debug='unidentified_string 4') # ' <None> ' data.uint32(debug='unidentified number 1') # 0 data.uint32(debug='unidentified number 2') # 0 data.uint32(debug='unidentified number 3') # 0 data.uint16(debug='unidentified number 4') # 1 for i in range(0, 16): data.string16(debug="ai player {}".format(i)) for i in range(0, 16): data.string16(debug="city plan player {}".format(i)) for i in range(0, 16): data.string16(debug="personality player {}".format(i)) for i in range(0, 16): some_length1 = data.uint32(debug='some length maybe') some_length2 = data.uint32(debug='some length maybe') some_length3 = data.uint32(debug='some length maybe') data.string_fixed(some_length1, debug='some string 1') data.string_fixed(some_length2, debug='some string 2') data.string_fixed(some_length3, debug='some string 3') check1 = data.int32(debug='check value 1') if check1 != -99: raise Exception("Check value did not match in scenario data, giving up") if version < 3.13: data.mark('extra data observed in 3.125 version') for i in range(0, 32): data.int32(debug='unknown value 1 {}'.format(i)) # 500 for i in range(0, 32): data.int32(debug='unknown value 2 {}'.format(i)) # 0 check2 = data.int32(debug='check value 2') if check2 != -99: raise Exception("Check value did not match in scenario data, giving up") rge_scen = ScnEngineProperties( version ) logging.debug(rge_scen) return rge_scen
def read(data: ScnDataReader): cmd_byte = data.uint8() if cmd_byte & 0x03 == 0x00: # "Lesser draw" draw_len = cmd_byte >> 2 draw_px = data.read(draw_len) # if draw len == 0 ?? return SlpDrawCommand(SlpDrawCommandType.PALETTE_PIXELS_DRAW, draw_len, draw_px) elif cmd_byte & 0x03 == 0x01: # "Lesser skip" draw_len = cmd_byte >> 2 if draw_len == 0: draw_len = data.uint8() return SlpDrawCommand(SlpDrawCommandType.TRANSPARENT_DRAW, draw_len, b"") elif cmd_byte & 0x0F == 0x02: # "Greater draw" draw_len = ((cmd_byte & 0xF0) << 4) + data.uint8() draw_px = data.read(draw_len) return SlpDrawCommand(SlpDrawCommandType.PALETTE_PIXELS_DRAW, draw_len, draw_px) elif cmd_byte & 0x0F == 0x03: # "Greater skip" draw_len = ((cmd_byte & 0xF0) << 4) + data.uint8() return SlpDrawCommand(SlpDrawCommandType.TRANSPARENT_DRAW, draw_len, b"") elif cmd_byte & 0x0F == 0x06: # "Player color draw" draw_len = cmd_byte >> 4 if draw_len == 0: draw_len = data.uint8() draw_px = data.read(draw_len) return SlpDrawCommand(SlpDrawCommandType.PLAYER_PIXELS_DRAW, draw_len, draw_px) elif cmd_byte & 0x0F == 0x07: # "Fill" draw_len = cmd_byte >> 4 if draw_len == 0: draw_len = data.uint8() draw_px = data.read(1) return SlpDrawCommand(SlpDrawCommandType.PALETTE_PIXEL_REPEAT, draw_len, draw_px) elif cmd_byte & 0x0F == 0x0A: # "Player color fill" draw_len = cmd_byte >> 4 if draw_len == 0: draw_len = data.uint8() draw_px = data.read(1) return SlpDrawCommand(SlpDrawCommandType.PLAYER_PIXEL_REPEAT, draw_len, draw_px) elif cmd_byte & 0x0F == 0x0B: draw_len = cmd_byte >> 4 if draw_len == 0: draw_len = data.uint8() return SlpDrawCommand(SlpDrawCommandType.SHADOW_DRAW, draw_len, b"") elif cmd_byte & 0x0F == 0x0E: cmd_idx = cmd_byte >> 4 return SlpDrawCommand(SlpDrawCommandType.EXTENDED_COMMAND, 1, bytes([cmd_idx])) elif cmd_byte == 0x0F: # ? Strange end of row?? return SlpDrawCommand(SlpDrawCommandType.END_OF_ROW, 0, b"") print(cmd_byte) raise Exception("Unrecognised SLP draw byte, file may be corrupt.")
def read(data: ScnDataReader): return TechnologyCost(data.int16(debug='resource'), data.int16(debug='amount'), data.uint8(debug='paid'))
def read_de(data: ScnDataReader): return ScenarioObject((data.float32(), data.float32(), data.float32()), data.uint32(), data.uint16(), data.uint8(), data.float32(), -1, -1)