예제 #1
0
animated = "animated" / Struct(base, "speed" / Float32l)

moving = "moving" / Struct(
    animated, "move_sprite" / Int16ul, "run_sprite" / Int16ul,
    "turn_speed" / Float32l, "size_class" / Byte, "trailing_unit" / Int16ul,
    "trailing_options" / Byte, "trailing_spacing" / Float32l,
    "move_algorithm" / Byte, "turn_radius" / Float32l,
    "turn_radius_speed" / Float32l, "maximum_yaw_per_second_moving" / Float32l,
    "stationary_yaw_per_revolution_time" / Float32l,
    "maximum_yaw_per_second_stationary" / Float32l)

action = "action" / Struct(
    moving, "default_task" / Int16ul, "search_radius" / Float32l,
    "work_rate" / Float32l, "handicap_work_rate" /
    If(lambda ctx: find_save_version(ctx) >= 25.06, Float32l), "drop_site" /
    Int16ul, "backup_drop_site" / Int16ul, "task_by_group" / Byte,
    "command_sound" / Int16ul, "move_sound" / Int16ul, "run_pattern" / Byte)

weapon = "weapon" / Struct("type" / Int16ul, "value" / Int16ul)

base_combat = "base_combat" / Struct(
    action, "base_armour" /
    IfThenElse(lambda ctx: find_version(ctx) != Version.AOK, Int16ul, Byte),
    "num_weapons" / Int16ul, "weapons" / Array(this.num_weapons, weapon),
    "num_armours" / Int16ul, "armours" / Array(this.num_armours, weapon),
    "defense_terrain_bonus" / Int16ul, "weapon_range_max" / Float32l,
    "area_effect_range" / Float32l, "attack_speed" / Float32l,
    "missile_id" / Int16ul, "base_hit_chance" / Int16ul,
    "break_off_combat" / Byte, "frame_delay" / Int16ul,
    "weapon_offset" / Struct("x" / Float32l, "y" / Float32l, "z" / Float32l),
예제 #2
0
"""Lobby."""

from construct import Array, Byte, Bytes, Flag, Int32ul, Padding, Peek, Struct, If, Computed, Embedded, Int32sl

from mgz.enums import GameTypeEnum, RevealMapEnum
from mgz.util import Version, find_save_version

# pylint: disable=invalid-name, bad-continuation

# Player inputs in the lobby, and several host settings.
lobby = "lobby" / Struct(
    If(lambda ctx: find_save_version(ctx) >= 13.34, Padding(5)),
    If(lambda ctx: find_save_version(ctx) >= 20.06, Padding(9)),
    Array(8, "teams" / Byte),  # team number selected by each player
    If(
        lambda ctx: ctx._.version not in (Version.DE, Version.HD),
        Padding(1),
    ),
    Peek("reveal_map_id" / Int32ul),
    RevealMapEnum("reveal_map" / Int32ul),
    "fog_of_war" / Int32ul,
    "map_size" / Int32ul,
    "population_limit_encoded" / Int32ul,
    "population_limit" /
    Computed(lambda ctx: ctx.population_limit_encoded *
             (25 if ctx._.version in
              [Version.USERPATCH14, Version.USERPATCH15] else 1)),
    Embedded(
        If(
            lambda ctx: ctx._.version != Version.AOK,
            Struct(Peek("game_type_id" / Byte), GameTypeEnum(
예제 #3
0
    Array(
        16,
        "player_data" / Struct(
            "active" / Int32ul,
            "human" / Int32ul,
            "civilization" / Int32ul,
            "constant" / Int32ul,  # 0x04 0x00 0x00 0x00
        )),
    Padding(5),
    "elapsed_time" / Float32l,
    "scenario_filename" /
    PascalString(lengthfield="scenario_filename_length" / Int16ul),
    If(
        lambda ctx: ctx._._.version == Version.DE,
        Struct(Padding(64),
               If(lambda ctx: find_save_version(ctx) >= 13.34, Padding(64)))))

# Scenarios have intro text, a bitmap, and cinematics.
messages = "messages" / Struct(
    "instruction_id" / Int32ul,
    "hints_id" / Int32ul,
    "victory_id" / Int32ul,
    "defeat_id" / Int32ul,
    "history_id" / Int32ul,
    "scouts_id" / If(lambda ctx: ctx._._.version != Version.AOK, Int32ul),
    "instructions_length" / Int16ul,
    "instructions" / Bytes(lambda ctx: ctx.instructions_length),
    "hints" / PascalString(lengthfield="hints_length" / Int16ul),
    "victory" / PascalString(lengthfield="victory_length" / Int16ul),
    "defeat" / PascalString(lengthfield="defeat_length" / Int16ul),
    "history" / PascalString(lengthfield="history_length" / Int16ul),
예제 #4
0
    Array(
        16,
        "player_data" / Struct(
            "active" / Int32ul,
            "human" / Int32ul,
            "civilization" / Int32ul,
            "constant" / Int32ul,  # 0x04 0x00 0x00 0x00
        )),
    Padding(5),
    "elapsed_time" / Float32l,
    "scenario_filename" /
    PascalString(lengthfield="scenario_filename_length" / Int16ul),
    If(
        lambda ctx: ctx._._.version == Version.DE,
        Struct(Padding(64),
               If(lambda ctx: find_save_version(ctx) >= 13.34, Padding(64)))))

# Scenarios have intro text, a bitmap, and cinematics.
messages = "messages" / Struct(
    "instruction_id" / Int32ul,
    "hints_id" / Int32ul,
    "victory_id" / Int32ul,
    "defeat_id" / Int32ul,
    "history_id" / Int32ul,
    "scouts_id" / If(lambda ctx: ctx._._.version != Version.AOK, Int32ul),
    "instructions_length" / Int16ul,
    "instructions" / Bytes(lambda ctx: ctx.instructions_length),
    "hints" / PascalString(lengthfield="hints_length" / Int16ul),
    "victory" / PascalString(lengthfield="victory_length" / Int16ul),
    "defeat" / PascalString(lengthfield="defeat_length" / Int16ul),
    "history" / PascalString(lengthfield="history_length" / Int16ul),
예제 #5
0
    "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,
    "game_options_version"/Int32ul,
    "dlc_count"/Int32ul,
    "dlc_ids"/Array(lambda ctx: ctx.dlc_count, Int32ul),
    "dataset_ref"/Int32ul,
예제 #6
0
    If(lambda ctx: find_version(ctx) == Version.DE, Bytes(19)),
    "has_sprite_list" / Byte, "sprite_list" /
    If(lambda ctx: ctx.has_sprite_list != 0,
       RepeatUntil(lambda x, lst, ctx: lst[-1].type == 0, sprite_list)),
    "de_effect_block" / If(
        lambda ctx: find_version(ctx) == Version.DE,
        Struct(
            Padding(4), "has_effect" / Byte, "effect" / If(
                lambda ctx: ctx.has_effect == 1,
                Struct(Padding(3), "length" / Int16ul,
                       "name" / Bytes(lambda ctx: ctx.length),
                       If(lambda ctx: ctx.length > 0, Padding(33)))),
            If(
                lambda ctx: ctx.effect is None or
                (ctx.effect and ctx.effect.length > 0), Byte), Padding(4),
            If(lambda ctx: find_save_version(ctx) >= 13.15, Padding(5)),
            If(lambda ctx: find_save_version(ctx) >= 13.17, Bytes(2)),
            If(lambda ctx: find_save_version(ctx) >= 13.34, Bytes(12)))))

animated = "animated" / Struct(Embedded(static), "turn_speed" / Float32l)

path_data = "path_data" / Struct(
    "id" / Int32ul, "linked_path_type" / Int32ul, "waypoint_level" / Int32ul,
    "path_id" / Int32ul, "waypoint" / Int32ul, "state" / Int32sl,
    "range" / Float32l, "target_id" / Int32ul, "pause_time" / Float32l,
    "continue_counter" / Int32ul, "flags" / Int32ul)

vector = Struct("x" / Float32l, "y" / Float32l, "z" / Float32l)

movement_data = "movement" / Struct("velocity" / vector,
                                    "acceleration" / vector)
예제 #7
0
 "trade_enabled"/Flag,
 "team_bonus_disabled"/Flag,
 "random_positions"/Flag,
 "all_techs"/Flag,
 "num_starting_units"/Byte,
 "lock_teams"/Flag,
 "lock_speed"/Flag,
 "multiplayer"/Flag,
 "cheats"/Flag,
 "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) >= 25.06, "unk"/Flag),  # maybe handicap
 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"/Int32ul,
     "ai_type"/de_string,
     "ai_civ_name_index"/Byte,
     "ai_name"/de_string,
     "name"/de_string,
예제 #8
0
 "trade_enabled" / Flag,
 "team_bonus_disabled" / Flag,
 "random_positions" / Flag,
 "all_techs" / Flag,
 "num_starting_units" / Byte,
 "lock_teams" / Flag,
 "lock_speed" / Flag,
 "multiplayer" / Flag,
 "cheats" / Flag,
 "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,
예제 #9
0
 "p6_tribute_recvd" / Float32l, "p7_tribute_recvd" / Float32l,
 "p8_tribute_recvd" / Float32l, "current_unit_worth" / Float32l,
 "current_building_worth" / Float32l, "total_food_gathered" / Float32l,
 "total_wood_gathered" / Float32l, "total_stone_gathered" / Float32l,
 "total_gold_gathered" / Float32l, "total_kill_and_raze_worth" / Float32l,
 "total_tribute_recvd" / Float32l, "total_value_of_razings" / Float32l,
 "castle_high" / Float32l, "wonder_high" / Float32l, "total_tribute_sent" /
 Float32l, "convert_min_adj" / Float32l, "convert_max_adj" / Float32l,
 "convert_resist_min_adj" / Float32l, "convert_resist_max_adj" / Float32l,
 "convert_building_min" / Float32l, "convert_building_max" / Float32l,
 "convert_building_chance" / Float32l, "spies" / Float32l,
 "value_wonders_castles" / Float32l, "food_score" / Float32l,
 "wood_score" / Float32l, "stone_score" / Float32l, "gold_score" / Float32l,
 Embedded(
     If(
         lambda ctx: find_save_version(ctx) >= 11.76,
         Struct(
             "wood_bonus0" / Float32l,
             "food_bonus0" / Float32l,
             "relic_rate" / Float32l,
             "heresy" / Float32l,
             "theocracy" / Float32l,
             "crenellations" / Float32l,
             "construction_rate_mod" / Float32l,
             "hun_wonder_bonus" / Float32l,
             "spies_discount" / Float32l,
         ))),
 Embedded(
     If(lambda ctx: find_version(ctx) in (Version.DE, Version.HD),
        Struct(Array(this._._.num_header_data - 198, Float32l)))),
 Embedded(
예제 #10
0
    If(lambda ctx: find_version(ctx) == Version.DE, Bytes(19)),
    "has_sprite_list" / Byte, "sprite_list" /
    If(lambda ctx: ctx.has_sprite_list != 0,
       RepeatUntil(lambda x, lst, ctx: lst[-1].type == 0, sprite_list)),
    "de_effect_block" / If(
        lambda ctx: find_version(ctx) == Version.DE,
        Struct(
            Padding(4), "has_effect" / Byte, "effect" / If(
                lambda ctx: ctx.has_effect == 1,
                Struct(Padding(3), "length" / Int16ul,
                       "name" / Bytes(lambda ctx: ctx.length),
                       If(lambda ctx: ctx.length > 0, Padding(33)))),
            If(
                lambda ctx: ctx.effect is None or
                (ctx.effect and ctx.effect.length > 0), Byte), Padding(4),
            If(lambda ctx: find_save_version(ctx) >= 13.15, Padding(5)),
            If(lambda ctx: find_save_version(ctx) >= 13.17, Bytes(2)),
            If(lambda ctx: find_save_version(ctx) >= 13.34, Bytes(12)))))

animated = "animated" / Struct(Embedded(static), "turn_speed" / Float32l)

path_data = "path_data" / Struct(
    "id" / Int32ul, "linked_path_type" / Int32ul, "waypoint_level" / Int32ul,
    "path_id" / Int32ul, "waypoint" / Int32ul, "state" / Int32sl,
    "range" / Float32l, "target_id" / Int32ul, "pause_time" / Float32l,
    "continue_counter" / Int32ul, "flags" / Int32ul)

vector = Struct("x" / Float32l, "y" / Float32l, "z" / Float32l)

movement_data = "movement" / Struct("velocity" / vector,
                                    "acceleration" / vector)
예제 #11
0
    "next_uid"/Int32ul,
    "constant"/Bytes(4),
    Array(16, "names"/String(256)),
    Array(16, "player_ids"/Int32ul),
    Array(16, "player_data"/Struct(
        "active"/Int32ul,
        "human"/Int32ul,
        "civilization"/Int32ul,
        "constant"/Int32ul, # 0x04 0x00 0x00 0x00
    )),
    Padding(5),
    "elapsed_time"/Float32l,
    "scenario_filename"/PascalString(lengthfield="scenario_filename_length"/Int16ul),
    If(lambda ctx: ctx._._.version == Version.DE, Struct(
        Padding(64),
        If(lambda ctx: find_save_version(ctx) >= 13.34, Padding(64))
    ))
)

# Scenarios have intro text, a bitmap, and cinematics.
messages = "messages"/Struct(
    "instruction_id"/Int32ul,
    "hints_id"/Int32ul,
    "victory_id"/Int32ul,
    "defeat_id"/Int32ul,
    "history_id"/Int32ul,
    "scouts_id"/If(lambda ctx: ctx._._.version != Version.AOK, Int32ul),
    "instructions_length"/Int16ul,
    "instructions"/Bytes(lambda ctx: ctx.instructions_length),
    "hints"/PascalString(lengthfield="hints_length"/Int16ul),
    "victory"/PascalString(lengthfield="victory_length"/Int16ul),
예제 #12
0
 "sleep"/Flag,
 "doppleganger"/Flag,
 "go_to_sleep"/Flag,
 "object_id"/Int32ul,
 "facet"/Byte,
 "x"/Float32l,
 "y"/Float32l,
 "z"/Float32l,
 "screen_offset_x"/Int16ul,
 "screen_offset_y"/Int16ul,
 "shadow_offset_x"/Int16ul,
 "shadow_offset_y"/Int16ul,
 "selected_group"/If(lambda ctx: find_version(ctx) == Version.AOK, Byte),
 ResourceEnum("resource_type"/Int16sl),
 "amount"/Float32l,
 "worker_count"/IfThenElse(lambda ctx: find_save_version(ctx) == 12.36, Int32ul, Byte),
 "current_damage"/Byte,
 "damaged_lately_timer"/Byte,
 "under_attack"/Byte,
 "pathing_group_len"/Int32ul,
 "pathing_group"/Array(lambda ctx: ctx.pathing_group_len, "object_id"/Int32ul),
 "group_id"/Int32sl,
 "roo_already_called"/Byte,
 "de_static_unk1"/If(lambda ctx: find_version(ctx) == Version.DE, Bytes(17)),
 If(lambda ctx: find_save_version(ctx) >= 26.16, Byte),
 "de_has_object_props"/If(lambda ctx: find_version(ctx) == Version.DE, Int16ul),
 "de_object_props"/IfThenElse(lambda ctx: ctx.de_has_object_props == 1, Struct(
     Bytes(162),
     Find(b'`\n\x00\x00`\n\x00\x00', 1000), # Skip a large unparseable block that (likely) contains RMS-modified object data
     Bytes(2)
 ), Struct(
예제 #13
0
    Array(
        16,
        "player_data" / Struct(
            "active" / Int32ul,
            "human" / Int32ul,
            "civilization" / Int32ul,
            "constant" / Int32ul,  # 0x04 0x00 0x00 0x00
        )),
    Padding(5),
    "elapsed_time" / Float32l,
    "scenario_filename" /
    PascalString(lengthfield="scenario_filename_length" / Int16ul),
    If(
        lambda ctx: ctx._._.version == Version.DE,
        Struct(Padding(64),
               If(lambda ctx: find_save_version(ctx) >= 13.34, Padding(64)))))

# Scenarios have intro text, a bitmap, and cinematics.
messages = "messages" / Struct(
    "instruction_id" / Int32ul,
    "hints_id" / Int32ul,
    "victory_id" / Int32ul,
    "defeat_id" / Int32ul,
    "history_id" / Int32ul,
    "scouts_id" / If(lambda ctx: ctx._._.version != Version.AOK, Int32ul),
    "instructions_length" / Int16ul,
    "instructions" / Bytes(lambda ctx: ctx.instructions_length),
    "hints" / PascalString(lengthfield="hints_length" / Int16ul),
    "victory" / PascalString(lengthfield="victory_length" / Int16ul),
    "defeat" / PascalString(lengthfield="defeat_length" / Int16ul),
    "history" / PascalString(lengthfield="history_length" / Int16ul),
예제 #14
0
    If(lambda ctx: find_version(ctx) == Version.DE, Bytes(19)),
    "has_sprite_list" / Byte, "sprite_list" /
    If(lambda ctx: ctx.has_sprite_list != 0,
       RepeatUntil(lambda x, lst, ctx: lst[-1].type == 0, sprite_list)),
    "de_effect_block" / If(
        lambda ctx: find_version(ctx) == Version.DE,
        Struct(
            Padding(4), "has_effect" / Byte, "effect" / If(
                lambda ctx: ctx.has_effect == 1,
                Struct(Padding(3), "length" / Int16ul,
                       "name" / Bytes(lambda ctx: ctx.length),
                       If(lambda ctx: ctx.length > 0, Padding(33)))),
            If(
                lambda ctx: ctx.effect is None or
                (ctx.effect and ctx.effect.length > 0), Byte), Padding(4),
            If(lambda ctx: find_save_version(ctx) >= 13.15, Padding(5)),
            If(lambda ctx: find_save_version(ctx) >= 13.17, Bytes(2)))))

animated = "animated" / Struct(Embedded(static), "turn_speed" / Float32l)

path_data = "path_data" / Struct(
    "id" / Int32ul, "linked_path_type" / Int32ul, "waypoint_level" / Int32ul,
    "path_id" / Int32ul, "waypoint" / Int32ul, "state" / Int32sl,
    "range" / Float32l, "target_id" / Int32ul, "pause_time" / Float32l,
    "continue_counter" / Int32ul, "flags" / Int32ul)

vector = Struct("x" / Float32l, "y" / Float32l, "z" / Float32l)

movement_data = "movement" / Struct("velocity" / vector,
                                    "acceleration" / vector)
예제 #15
0
 "doppleganger" / Flag,
 "go_to_sleep" / Flag,
 "object_id" / Int32ul,
 "facet" / Byte,
 "x" / Float32l,
 "y" / Float32l,
 "z" / Float32l,
 "screen_offset_x" / Int16ul,
 "screen_offset_y" / Int16ul,
 "shadow_offset_x" / Int16ul,
 "shadow_offset_y" / Int16ul,
 "selected_group" / If(lambda ctx: find_version(ctx) == Version.AOK, Byte),
 ResourceEnum("resource_type" / Int16sl),
 "amount" / Float32l,
 "worker_count" /
 IfThenElse(lambda ctx: find_save_version(ctx) == 12.36, Int32ul, Byte),
 "current_damage" / Byte,
 "damaged_lately_timer" / Byte,
 "under_attack" / Byte,
 "pathing_group_len" / Int32ul,
 "pathing_group" /
 Array(lambda ctx: ctx.pathing_group_len, "object_id" / Int32ul),
 "group_id" / Int32sl,
 "roo_already_called" / Byte,
 "de_static_unk1" /
 If(lambda ctx: find_version(ctx) == Version.DE, Bytes(19)),
 "has_sprite_list" / Byte,
 "sprite_list" /
 If(lambda ctx: ctx.has_sprite_list != 0,
    RepeatUntil(lambda x, lst, ctx: lst[-1].type == 0, sprite_list)),
 "hd_extension" / If(