Array(16, "num_disabled_units" / Int32ul), Array(16, Array(30, Padding(4))), Array(16, "num_disabled_buildings" / Int32ul), Array(16, Array(20, Padding(4))), ), Padding(196)), Padding(12)) # Game settings. game_settings = "game_settings" / Struct( Array(16, AgeEnum("starting_ages" / Int32sl)), Padding(4), Padding(8), "map_id" / If(lambda ctx: ctx._._.version != Version.AOK, Int32ul), Peek("difficulty_id" / Int32ul), DifficultyEnum( "difficulty" / Int32ul), "lock_teams" / Int32ul, If(lambda ctx: ctx._._.version == Version.DE, Padding(29)), Array( 9, "player_info" / Struct("data_ref" / Int32ul, PlayerTypeEnum("type" / Int32ul), "name" / PascalString(lengthfield="name_length" / Int32ul))), Padding(36), Padding(4), IfThenElse( lambda ctx: ctx._._.version == Version.DE, "end_of_game_settings" / Find(b'\x9a\x99\x99\x99\x99\x99\x01\x40', None), "end_of_game_settings" / Find(b'\x9a\x99\x99\x99\x99\x99\xf9\x3f', None))) # Triggers. triggers = "triggers" / Struct( Padding(1), "num_triggers" / Int32ul, # parse if num > 0 If(lambda ctx: ctx._._.version == Version.DE, Padding(1032))) # Scenario metadata.
test_57 = "test_57" / Struct( "check" / Int32ul, Padding(4), If(lambda ctx: ctx._._.version >= 1006, Bytes(1)), Padding(15), hd_string, Padding(1), If(lambda ctx: ctx._._.version >= 1005, hd_string), hd_string, Padding(16), "test" / Int32ul, "is_57" / Computed(lambda ctx: ctx.check == ctx.test)) player = Struct( "dlc_id" / Int32ul, "color_id" / Int32ul, "unk1_1006" / If(lambda ctx: ctx._._.version >= 1006, Bytes(1)), "unk" / Bytes(2), "dat_crc" / Bytes(4), "mp_game_version" / Byte, "team_index" / Int32ul, "civ_id" / Int32ul, "ai_type" / hd_string, "ai_civ_name_index" / Byte, "ai_name" / If(lambda ctx: ctx._._.version >= 1005, hd_string), "name" / hd_string, "type" / PlayerTypeEnum(Int32ul), "steam_id" / Int64ul, "player_number" / Int32sl, Embedded( If(lambda ctx: ctx._._.version >= 1006 and not ctx._.test_57.is_57, Struct( "hd_rm_rating" / Int32ul, "hd_dm_rating" / Int32ul, )))) hd = "hd" / Struct( "version" / Float32l, "interval_version" / Int32ul, "game_options_version" / Int32ul, "dlc_count" / Int32ul, "dlc_ids" / Array(lambda ctx: ctx.dlc_count, Int32ul), "dataset_ref" / Int32ul, Peek("difficulty_id" / Int32ul), DifficultyEnum("difficulty" / Int32ul), "selected_map_id" / Int32ul, "resolved_map_id" / Int32ul, "reveal_map" / Int32ul,
separator = Const(b"\xa3_\x02\x00") player = Struct( "dlc_id"/Int32ul, "color_id"/Int32sl, "selected_color"/Byte, "selected_team_id"/Byte, "resolved_team_id"/Byte, "dat_crc"/Bytes(8), "mp_game_version"/Byte, "civ_id"/Int32ul, "ai_type"/de_string, "ai_civ_name_index"/Byte, "ai_name"/de_string, "name"/de_string, "type"/PlayerTypeEnum(Int32ul), "profile_id"/Int32ul, Const(b"\x00\x00\x00\x00"), "player_number"/Int32sl, "hd_rm_elo"/If(lambda ctx: find_save_version(ctx) < 25.22, Int32ul), "hd_dm_elo"/If(lambda ctx: find_save_version(ctx) < 25.22, Int32ul), "prefer_random"/Flag, "custom_ai"/Flag, If(lambda ctx: find_save_version(ctx) >= 25.06, "handicap"/Bytes(8)), ) de = "de"/Struct( "build"/If(lambda ctx: find_save_version(ctx) >= 25.22, Int32ul), "timestamp"/If(lambda ctx: find_save_version(ctx) >= 26.16, Int32ul), "version"/Float32l, "interval_version"/Int32ul,
"record_game" / Flag, "animals_enabled" / Flag, "predators_enabled" / Flag, "turbo_enabled" / Flag, "shared_exploration" / Flag, "team_positions" / Flag, If(lambda ctx: find_save_version(ctx) >= 13.34, Bytes(8)), separator, "players" / Array( 8, Struct("dlc_id" / Int32ul, "color_id" / Int32sl, "selected_color" / Byte, "selected_team_id" / Byte, "resolved_team_id" / Byte, "dat_crc" / Bytes(8), "mp_game_version" / Byte, "civ_id" / Byte, Const(b"\x00\x00\x00"), "ai_type" / de_string, "ai_civ_name_index" / Byte, "ai_name" / de_string, "name" / de_string, "type" / PlayerTypeEnum(Int32ul), "profile_id" / Int32ul, Const(b"\x00\x00\x00\x00"), "player_number" / Int32sl, "hd_rm_elo" / Int32ul, "hd_dm_elo" / Int32ul, "animated_destruction_enabled" / Flag, "custom_ai" / Flag)), "fog_of_war" / Flag, "cheat_notifications" / Flag, "colored_chat" / Flag, Bytes(9), separator, Bytes(12), If(lambda ctx: ctx._.save_version >= 13.13, Bytes(5)), "strings" / Array( 23, Struct( "string" / de_string, RepeatUntil(
Padding(8), "map_id"/If(lambda ctx: ctx._._.version != Version.AOK, Int32ul), Peek("difficulty_id"/Int32ul), DifficultyEnum("difficulty"/Int32ul), "lock_teams"/Int32ul, If(lambda ctx: ctx._._.version == Version.DE, Struct( Padding(29), If(lambda ctx: find_save_version(ctx) >= 13.07, Padding(1)), If(lambda ctx: find_save_version(ctx) >= 13.34, Padding(132)), If(lambda ctx: find_save_version(ctx) >= 20.06, Padding(1)) ) ), Array(9, "player_info"/Struct( "data_ref"/Int32ul, PlayerTypeEnum("type"/Int32ul), "name"/PascalString(lengthfield="name_length"/Int32ul) )), Padding(36), Padding(4), IfThenElse(lambda ctx: ctx._._.version == Version.DE, IfThenElse(lambda ctx: find_save_version(ctx) >= 13.34, "end_of_game_settings"/Find(b'\x33\x33\x33\x33\x33\x33\x03\x40', None), "end_of_game_settings"/Find(b'\x9a\x99\x99\x99\x99\x99\x01\x40', None) ), "end_of_game_settings"/Find(b'\x9a\x99\x99\x99\x99\x99\xf9\\x3f', None) ) ) # Triggers. triggers = "triggers"/Struct(
Array(16, "num_disabled_buildings" / Int32ul), Array(16, Array(20, Padding(4))), Padding(12), ) # Game settings. game_settings = "game_settings" / Struct( Array(16, StartingAgeEnum("starting_ages" / Int32sl)), Padding(4), Padding(8), MapAdapter("map_id" / Int32ul), DifficultyEnum("difficulty" / Int32ul), Padding(4), Array( 9, "player_info" / Struct("player_id" / Int32ul, PlayerTypeEnum("type" / Int32ul), "name" / PascalString(lengthfield="name_length" / Int32ul))), Padding(36), Padding(4), "end_of_game_settings" / Find(b'\x9a\x99\x99\x99\x99\x99\xf9\x3f', None), ) # Triggers. triggers = "triggers" / Struct( Padding(1), "num_triggers" / Int32ul, # parse if num > 0 ) # Scenario metadata. scenario = "scenario" / Struct(