示例#1
0
def create_spriteset_actions(spritegroup):
    """
    Create action2s for directly-referenced sprite sets

    @param spritegroup: Spritegroup to create the sprite sets for
    @type spritegroup: L{ASTSpriteGroup}

    @return: Resulting list of actions
    @rtype: C{list} of L{BaseAction}
    """
    action_list = []
    # Iterate over features first for more efficient action1s
    for feature in spritegroup.feature_set:
        if len(spritegroup.used_sprite_sets
               ) != 0 and feature not in action2.features_sprite_group:
            raise generic.ScriptError(
                "Directly referring to sprite sets is not possible for feature {:02X}"
                .format(feature), spritegroup.pos)
        for spriteset in spritegroup.used_sprite_sets:
            if spriteset.has_action2(feature):
                continue
            action_list.extend(
                action1.add_to_action1([spriteset], feature, spritegroup.pos))

            real_action2 = make_simple_real_action2(
                feature,
                spriteset.name.value + " - feature {:02X}".format(feature),
                spritegroup.pos,
                action1.get_action1_index(spriteset),
            )
            action_list.append(real_action2)
            spriteset.set_action2(real_action2, feature)
    return action_list
示例#2
0
def get_real_action2s(spritegroup, feature):
    loaded_list = []
    loading_list = []
    actions = []

    if feature not in action2.features_sprite_group:
        raise generic.ScriptError("Sprite groups that combine sprite sets are not supported for feature '{}'.".format(general.feature_name(feature)), spritegroup.pos)

    # First make sure that all referenced real sprites are put in a single action1
    spriteset_list = []
    for view in spritegroup.spriteview_list:
        spriteset_list.extend([action2.resolve_spritegroup(sg_ref.name) for sg_ref in view.spriteset_list])
    actions.extend(action1.add_to_action1(spriteset_list, feature, spritegroup.pos))

    view_names = sorted([view.name.value for view in spritegroup.spriteview_list])
    if feature in (0x00, 0x01, 0x02, 0x03):
        if view_names != sorted(['loading', 'loaded']):
            raise generic.ScriptError("Expected a 'loading' and a 'loaded' (list of) sprite set(s).", spritegroup.pos)
    elif feature in (0x05, 0x0B, 0x0D, 0x10):
        msg = "Sprite groups for feature {:02X} will not be supported in the future, as they are no longer needed. Directly refer to sprite sets instead."
        msg = msg.format(feature)
        generic.print_warning(msg, spritegroup.pos)
        if view_names != ['default']:
            raise generic.ScriptError("Expected only a 'default' (list of) sprite set(s).", spritegroup.pos)

    for view in spritegroup.spriteview_list:
        if len(view.spriteset_list) == 0:
            raise generic.ScriptError("Expected at least one sprite set, encountered 0.", view.pos)
        for set_ref in view.spriteset_list:
            spriteset = action2.resolve_spritegroup(set_ref.name)
            action1_index = action1.get_action1_index(spriteset)
            if view.name.value == 'loading': loading_list.append(action1_index)
            else: loaded_list.append(action1_index)

    actions.append(Action2Real(feature, spritegroup.name.value + " - feature {:02X}".format(feature), spritegroup.pos, loaded_list, loading_list))
    spritegroup.set_action2(actions[-1], feature)
    return actions
示例#3
0
def get_layout_action2s(spritelayout, feature, spr_pos):
    """
    @param spr_pos: Position information of the sprite view.
    @type  spr_pos: L{Position}
    """
    ground_sprite = None
    building_sprites = []
    actions = []

    if feature not in action2.features_sprite_layout:
        raise generic.ScriptError(
            "Sprite layouts are not supported for feature '{}'.".format(
                general.feature_name(feature)))

    # Allocate registers
    param_map = {}
    param_registers = []
    for param in spritelayout.param_list:
        reg = action2var.VarAction2CallParam(param.value)
        param_registers.append(reg)
        param_map[param.value] = reg
    param_map = (param_map, lambda name, value, pos: action2var.
                 VarAction2LoadCallParam(value, name))
    spritelayout.register_map[feature] = param_registers

    # Reduce all expressions, can't do that earlier as feature is not known
    all_sprite_sets = []
    layout_sprite_list = []  # Create a new structure
    for layout_sprite in spritelayout.layout_sprite_list:
        param_list = []
        layout_sprite_list.append(
            (layout_sprite.type, layout_sprite.pos, param_list))
        for param in layout_sprite.param_list:
            param_val = action2var.reduce_varaction2_expr(
                param.value, action2var.get_scope(feature), [param_map])
            param_list.append((param.name, param_val))
            if isinstance(param_val, expression.SpriteGroupRef):
                spriteset = action2.resolve_spritegroup(param_val.name)
                if not spriteset.is_spriteset():
                    raise generic.ScriptError(
                        "Expected a reference to a spriteset.", param_val.pos)
                all_sprite_sets.append(spriteset)
    actions.extend(
        action1.add_to_action1(all_sprite_sets, feature, spritelayout.pos))

    temp_registers = []
    for type, pos, param_list in layout_sprite_list:
        if type.value not in layout_sprite_types:
            raise generic.ScriptError(
                "Invalid sprite type '{}' encountered. Expected 'ground', 'building', or 'childsprite'."
                .format(type.value),
                type.pos,
            )
        sprite = Action2LayoutSprite(feature, layout_sprite_types[type.value],
                                     pos, [param_map])
        for name, value in param_list:
            sprite.set_param(name, value)
        temp_registers.extend(sprite.get_all_registers())
        if sprite.type == Action2LayoutSpriteType.GROUND:
            if ground_sprite is not None:
                raise generic.ScriptError(
                    "Sprite layout can have no more than one ground sprite",
                    spritelayout.pos)
            ground_sprite = sprite
        else:
            building_sprites.append(sprite)

    if ground_sprite is None:
        if len(building_sprites) == 0:
            # no sprites defined at all, that's not very much.
            raise generic.ScriptError(
                "Sprite layout requires at least one sprite", spr_pos)
        # set to 0 for no ground sprite
        ground_sprite = Action2LayoutSprite(feature,
                                            Action2LayoutSpriteType.GROUND)
        ground_sprite.set_param(expression.Identifier("sprite"),
                                expression.ConstantNumeric(0))

    action6.free_parameters.save()
    act6 = action6.Action6()

    advanced = any(x.is_advanced_sprite()
                   for x in building_sprites + [ground_sprite])

    offset = 4
    sprite_num = ground_sprite.get_sprite_number()
    sprite_num, offset = actionD.write_action_value(sprite_num, actions, act6,
                                                    offset, 4)
    if advanced:
        offset += ground_sprite.get_registers_size()

    for sprite in building_sprites:
        sprite_num = sprite.get_sprite_number()
        sprite_num, offset = actionD.write_action_value(
            sprite_num, actions, act6, offset, 4)
        if advanced:
            offset += sprite.get_registers_size()
        offset += 3 if sprite.type == Action2LayoutSpriteType.CHILD else 6

    if len(act6.modifications) > 0:
        actions.append(act6)

    layout_action = Action2Layout(
        feature,
        spritelayout.name.value + " - feature {:02X}".format(feature),
        spritelayout.pos,
        ground_sprite,
        building_sprites,
        param_registers,
    )
    actions.append(layout_action)

    if temp_registers:
        varact2parser = action2var.Varaction2Parser(
            feature, action2var.get_scope(feature))
        for register_info in temp_registers:
            reg, expr = register_info[1], register_info[2]
            if reg is None:
                continue
            varact2parser.parse_expr(expr)
            varact2parser.var_list.append(nmlop.STO_TMP)
            varact2parser.var_list.append(reg)
            varact2parser.var_list.append(nmlop.VAL2)
            varact2parser.var_list_size += reg.get_size() + 2

    # Only continue if we actually needed any new registers
    if temp_registers and varact2parser.var_list:  # lgtm[py/uninitialized-local-variable]
        # Remove the last VAL2 operator
        varact2parser.var_list.pop()
        varact2parser.var_list_size -= 1

        actions.extend(varact2parser.extra_actions)
        extra_act6 = action6.Action6()
        for mod in varact2parser.mods:
            extra_act6.modify_bytes(mod.param, mod.size, mod.offset + 4)
        if len(extra_act6.modifications) > 0:
            actions.append(extra_act6)

        varaction2 = action2var.Action2Var(
            feature,
            "{}@registers - feature {:02X}".format(spritelayout.name.value,
                                                   feature), spritelayout.pos,
            0x89)
        varaction2.var_list = varact2parser.var_list
        ref = expression.SpriteGroupRef(spritelayout.name, [], None,
                                        layout_action)
        varaction2.ranges.append(
            action2var.VarAction2Range(expression.ConstantNumeric(0),
                                       expression.ConstantNumeric(0), ref, ""))
        varaction2.default_result = ref
        varaction2.default_comment = ""

        # Add two references (default + range)
        # Make sure that registers allocated here are not used by the spritelayout
        action2.add_ref(ref, varaction2, True)
        action2.add_ref(ref, varaction2, True)
        spritelayout.set_action2(varaction2, feature)
        actions.append(varaction2)
    else:
        spritelayout.set_action2(layout_action, feature)

    action6.free_parameters.restore()
    return actions