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_de(data: ScnDataReader): base = ScnEngineProperties.read_de(data) # expecting global victory conditions around here somewhere for i in range(0, 8): data.uint32(debug='unknown value a {}'.format(i)) data.uint32(debug='unknown value b') # 900 data.uint32(debug='unknown value c') # 9000 # expecting diplomacy for i in range(0, 16): for j in range(0, 16): val = data.uint32() logging.debug("Unknown value from=%d to=%d val=%d", i, j, val) # lots of '3'. # expecting 12 individual victory conditions for each player for i in range(0, 16): for j in range(0, 12): # TODO read these ??? data.read(60) check3 = data.int32(debug='check value 3') if check3 != -99: raise Exception( "Check value did not match in scenario data, giving up") # Probably allied victory for i in range(0, 16): data.uint32(debug='allied victory player {}'.format(i)) # disabled tech for i in range(0, 16): for j in range(0, 20): disabled_tech_id = data.uint32() logging.debug("Disabled tech player %d, position %d: %d", i, j, disabled_tech_id) data.uint32(debug='unknown field 1') data.uint32(debug='unknown field 2') data.uint32(debug='unknown field 3') # might be full tech tree for j in range(0, 16): # maybe ? data.uint32(debug='starting age player {}'.format(j)) check4 = data.int32(debug='check value 2') if check4 != -99: raise Exception( "Check value did not match in scenario data, giving up") # view ? data.float32() data.float32() game_properties = ScnGameProperties(base) logging.debug(game_properties) return game_properties
def read_missile_unit(data: ScnDataReader): base_props = read_base_unit_props(data) animated_props = read_animated_unit_props(data) moving_unit_props = read_moving_unit_props(data) action_unit_props = read_action_unit_props(data) base_combat_unit_props = read_base_combat_unit_props(data) data.int8(debug='unknown') data.int32(debug='unknown') data.float32(debug='unknown')
def read(data: ScnDataReader): unit_type = data.uint32() terrain_type = data.int32() group_flag = data.int8() scale_flag = data.int8() _padding5 = data.uint16() group_size = data.int32() group_size_variance = data.int32() group_count = data.int32() group_area = data.int32() player_id = data.int32() land_id = data.int32() min_distance_to_players = data.int32() max_distance_to_players = data.int32() return RandomMapObject( unit_type, terrain_type, group_flag, scale_flag, group_size, group_size_variance, group_count, group_area, player_id, land_id, min_distance_to_players, max_distance_to_players )
def read(data: ScnDataReader): percent = data.uint32() height = data.int32() clumps = data.int32() spacing = data.int32() base_terrain_type = data.int32() base_elevation_type = data.int32() return RandomMapElevation( percent, height, clumps, spacing, base_terrain_type, base_elevation_type )
def read(data: ScnDataReader): random_map_num_lands = data.int32(debug='random_map_land_count') pointer = data.uint32(debug='random_map_land_pointer') items = [RandomMapLand.read(data) for _ in range(0, random_map_num_lands)] return RandomMapLandListWrapper( pointer, items )
def read(data: ScnDataReader): random_map_num_terrains = data.int32(debug='random_map_terrain_count') # could be land ID?? pointer = data.uint32(debug='random_map_terrain_pointer') items = [RandomMapTerrain.read(data) for _ in range(0, random_map_num_terrains)] return RandomMapTerrainListWrapper( pointer, items )
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 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): terrain_percent = data.int32(debug='random_map_terrain_percent') terrain_terrain_type = data.int32(debug='random_map_terrain_type') terrain_clumps = data.int32(debug='random_map_terrain_clumps') terrain_spacing = data.int32(debug='random_map_terrain_spacing') terrain_base_terrain_type = data.int32(debug='random_map_terraint_type') terrain_clumpiness_factor = data.int32(debug='random_map_terrain_clumpiness_factor') return RandomMapTerrain( terrain_percent, terrain_terrain_type, terrain_clumps, terrain_spacing, terrain_base_terrain_type, terrain_clumpiness_factor )
def read(data: ScnDataReader): id = data.uint32(debug='random_map_id') borders = ( data.uint32(debug='random_map_border_1'), data.uint32(debug='random_map_border_2'), data.uint32(debug='random_map_border_3'), data.uint32(debug='random_map_border_4') ) border_usage = data.uint32(debug='random_map_border_usage') water_shape = data.uint32(debug='random_map_water_shape') base_terrain = data.uint32(debug='random_map_base_terrain') land_cover = data.uint32(debug='random_map_land_cover') unused_id = data.uint32(debug='random_map_border_unused_id') num_lands = data.uint32(debug='random_map_num_lands') pointer1 = data.uint32() num_terrains = data.uint32(debug='random_map_num_terrains') pointer2 = data.uint32() num_objects = data.uint32(debug='random_map_num_objects') pointer3 = data.uint32() num_elevations = data.uint32(debug='random_map_num_elevations') pointer4 = data.int32() return RandomMapMeta( id, borders, border_usage, water_shape, base_terrain, land_cover, unused_id, num_lands, pointer1, num_terrains, pointer2, num_objects, pointer3, num_elevations, pointer4 )
def read_classic(data: ScnDataReader): base = ScnEngineProperties.read_classic(data) version = base.rge_version if version <= 1.13: for i in range(0, 16): # skip past player names player_name = data.string_fixed(size=256) raise Exception( "Not implemented: Don't know how to read player base properties from <1.13 file" ) else: player_start_resources = [] for i in range(0, 16): # Ignoring at the moment this_player_start_resources = ScnPlayerStartResources.read( data, version) player_start_resources.append(this_player_start_resources) if version >= 1.02: check5 = data.int32() if check5 != -99: raise Exception( "Check value did not match in scenario data, giving up") victory_conquest = data.uint32() victory_ruins = data.uint32() victory_artifacts = data.uint32() victory_discoveries = data.uint32() victory_exploration = data.uint32() victory_gold = data.uint32() victory_all_flag = data.boolean32() if version >= 1.13: mp_victory_type = data.uint32() victory_score = data.uint32() victory_time = data.uint32() for i in range(0, 16): for j in range(0, 16): stance = data.uint32() logging.debug("Diplomacy from=%d to=%d stance=%d", i, j, stance) # 12 victory conditions for each player for i in range(0, 16): for j in range(0, 12): # TODO read these ??? individual_victory_blob = data.read(60) if version >= 1.02: check5 = data.int32() if check5 != -99: raise Exception( "Check value did not match in scenario data, giving up") # Allied victory for i in range(0, 16): allied_victory = data.uint32() if version >= 1.24: raise Exception( "Not implemented: Don't know how to read team information from >=1.24 file" ) if version >= 1.18: # Also has disabled units and building, where are they in older versions? raise Exception( "Not implemented: Don't know how to read tech tree from >=1.18 file" ) elif version > 1.03: for i in range(0, 16): for j in range(0, 20): disabled_tech_id = data.uint32() logging.debug("Disabled tech player %d, position %d: %d", i, j, disabled_tech_id) if version > 1.04: data.uint32() # No idea if version >= 1.12: data.uint32() # No idea full_tech_tree = data.boolean32() if version > 1.05: for i in range(0, 16): player_start_age = data.uint32() if version >= 1.02: check6 = data.int32() if check6 != -99: raise Exception( "Check value did not match in scenario data, giving up") if version >= 1.19: # 'view'?? data.uint32() data.uint32() if version >= 1.21: raise Exception( "Not implemented: Don't know how to read map type from >=1.21 file" ) if version >= 1.21: raise Exception( "Not implemented: Don't know how to read base priorities from >=1.21 file" ) game_properties = ScnGameProperties(base) logging.debug(game_properties) return game_properties
def read_classic(data: ScnDataReader): # TODO actually store this stuff version = data.float32(debug='version') if version > 1.13: for i in range(0, 16): # skip past player names player_name = data.string_fixed(size=256) if version > 1.16: raise Exception("Not implemented: player string table not understood") if version > 1.13: for i in range(0, 16): player_base = ScnPlayerBaseProperties.read(data) logging.debug(player_base) is_conquest = False if version > 1.07: is_conquest = data.boolean8() # Something to do with timelines? check1 = data.uint16() check2 = data.uint16() check3 = data.float32() if check1 != 0 or check2 != 0 or check3 < -1 or check3 > 1: raise Exception("Unexpected values in scenario data, giving up") filename = data.string16(debug='filename') if version > 1.16: raise Exception("Not implemented: scenario instruction string table not understood") if version > 1.22: raise Exception("Not implemented: scout string table not understood") description = data.string16(debug='description') if version >= 1.11: hints_message = data.string16(debug='hints_message') win_message = data.string16(debug='win_message') loss_message = data.string16(debug='loss_message') history_message = data.string16(debug='history_message') if version > 1.22: raise Exception("Not implemented: scout data not understood") pregame_cinematic = data.string16(debug='pregame_cinematic') victory_cinematic = data.string16(debug='victory_cinematic') loss_cinematic = data.string16(debug='loss_cinematic') if version >= 1.09: mission_bmp = data.string16() logging.debug("mission_bmp='%s'", mission_bmp) if version >= 1.10: mission_image = data.uint32() width = data.uint32() height = data.uint32() orientation = data.uint16() if width > 0 or height > 0: raise Exception("Mission BMP data not understood") for i in range(0, 16): player_build_list = data.string16() logging.debug("Player %d build list %s", i, player_build_list) for i in range(0, 16): player_city_plan = data.string16() logging.debug("Player %d city plan %s", i, player_city_plan) if version >= 1.08: for i in range(0, 16): player_personality = data.string16() logging.debug("Player %d personality %s", i, player_personality) for i in range(0, 16): """ Embedded files """ build_list_length = data.uint32() city_plan_length = data.uint32() ai_rules_length = data.uint32() if version >= 1.08 else 0 data.read(build_list_length) data.read(city_plan_length) data.read(ai_rules_length) if version >= 1.20: raise Exception("Not implemented: AI rules not understood") if version >= 1.02: check4 = data.int32() if check4 != -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_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): return SlpFrameInfo(data.uint32(), data.uint32(), data.uint32(), data.uint32(), data.int32(), data.int32(), data.int32(), data.int32())