Esempio n. 1
0
def flag_brush_at_loc(inst, flag):
    """Checks to see if a wall is present at the given location.

    - Pos is the position of the brush, where `0 0 0` is the floor-position
       of the brush.
    - Dir is the normal the face is pointing. (0 0 -1) is 'up'.
    - Type defines the type the brush must be:
      - "Any" requires either a black or white brush.
      - "None" means that no brush must be present.
      - "White" requires a portalable surface.
      - "Black" requires a non-portalable surface.
    - SetVar defines an instvar which will be given a value of "black",
      "white" or "none" to allow the result to be reused.
    - If gridPos is true, the position will be snapped so it aligns with
      the 128 brushes (Useful with fizzler/light strip items).
    - RemoveBrush: If set to 1, the brush will be removed if found.
      Only do this to EmbedFace brushes, since it will remove the other
      sides as well.
    """
    from conditions import VMF
    pos = Vec.from_str(flag['pos', '0 0 0'])
    pos.z -= 64  # Subtract so origin is the floor-position
    pos = pos.rotate_by_str(inst['angles', '0 0 0'])

    # Relative to the instance origin
    pos += Vec.from_str(inst['origin', '0 0 0'])

    norm = Vec.from_str(flag['dir', '0 0 -1']).rotate_by_str(
        inst['angles', '0 0 0']
    )

    if utils.conv_bool(flag['gridpos', '0']):
        for axis in 'xyz':
            # Don't realign things in the normal's axis -
            # those are already fine.
            if norm[axis] == 0:
                pos[axis] = pos[axis] // 128 * 128 + 64

    result_var = flag['setVar', '']
    should_remove = utils.conv_bool(flag['RemoveBrush', False], False)
    des_type = flag['type', 'any'].casefold()

    brush = SOLIDS.get(pos.as_tuple(), None)

    if brush is None or brush.normal != norm:
        br_type = 'none'
    else:
        br_type = str(brush.color)
        if should_remove:
            VMF.remove_brush(
                brush.solid,
            )

    if result_var:
        inst.fixup[result_var] = br_type

    if des_type == 'any' and br_type != 'none':
        return True

    return des_type == br_type
Esempio n. 2
0
    def update(self):
        if Player.getState() == "IDLE":
            return
        # update pos, velocity, interval
        self.updateVelAndIntrvl()
        if pyxel.frame_count % 2:
            for i in range(len(self.pos)):
                self.pos[i] = Vec(self.pos[i].x + self.velocity.x,
                                  self.pos[i].y)

        # 左端についたら右端に戻す
        for i in range(self.ENEMY_NUM):
            if self.pos[i].x < -50:
                # reset pos
                interval = random.randrange(self.MIN_INTERVAL,
                                            self.MAX_INTERVAL)
                spawn_x = max(self.pos[i - 1].x, self.SPAWN_POS)
                self.pos[i] = Vec(spawn_x + interval, self.GND_HEIGHT)

                # select cactus or ptera at random
                if random.random() < self.PTERA_SPAWN_RATIO:  # ptera
                    self.cur_anim[i] = Enemy.PTERA_ANIMs[0]
                    self.pos[i].y -= 40 * random.randrange(0, 2)
                else:  # cactus
                    self.cur_anim[i] = Enemy.CACTUS_ANIMs[random.randrange(
                        0, 2)]

        if self.collideWithPlayer():
            Player.beGameover()
Esempio n. 3
0
def res_replace_instance(inst: VLib.Entity, res):
    """Replace an instance with another entity.

    'keys' and 'localkeys' defines the new keyvalues used.
    'targetname' and 'angles' are preset, and 'origin' will be used to offset
    the given amount from the current location.
    If 'keep_instance' is true, the instance entity will be kept instead of
    removed.
    """
    import vbsp

    origin = Vec.from_str(inst['origin'])
    angles = inst['angles']

    if not utils.conv_bool(res['keep_instance', '0'], False):
        inst.remove()  # Do this first to free the ent ID, so the new ent has
        # the same one.

    # We copy to allow us to still acess the $fixups and other values.
    new_ent = inst.copy(des_id=inst.id)
    new_ent.clear_keys()
    # Ensure there's a classname, just in case.
    new_ent['classname'] = 'info_null'

    vbsp.VMF.add_ent(new_ent)

    conditions.set_ent_keys(new_ent, inst, res)

    origin += Vec.from_str(new_ent['origin']).rotate_by_str(angles)
    new_ent['origin'] = origin
    new_ent['angles'] = angles
    new_ent['targetname'] = inst['targetname']
Esempio n. 4
0
def res_faith_mods(inst, res):
    """Modify the trigger_catrapult that is created for ItemFaithPlate items.

    """
    # Get data about the trigger this instance uses for flinging
    fixup_var = res["instvar", ""]
    offset = utils.conv_int(res["raise_trig", "0"])
    if offset:
        angle = Vec.from_str(inst["angles", "0 0 0"])
        offset = Vec(0, 0, offset).rotate(angle.x, angle.y, angle.z)
        ":type offset Vec"
    for trig in VMF.by_class["trigger_catapult"]:
        if inst["targetname"] in trig["targetname"]:
            if offset:  # Edit both the normal and the helper trigger
                trig["origin"] = (Vec.from_str(trig["origin"]) + offset).join(" ")
                for solid in trig.solids:
                    solid.translate(offset)

            for out in trig.outputs:
                if out.inst_in == "animate_angled_relay":
                    out.inst_in = res["angled_targ", "animate_angled_relay"]
                    out.input = res["angled_in", "Trigger"]
                    if fixup_var:
                        inst.fixup[fixup_var] = "angled"
                    break
                elif out.inst_in == "animate_straightup_relay":
                    out.inst_in = res["straight_targ", "animate_straightup_relay"]
                    out.input = res["straight_in", "Trigger"]
                    if fixup_var:
                        inst.fixup[fixup_var] = "straight"
                    break
Esempio n. 5
0
def res_fizzler_pair(begin_inst, res):
    """Modify the instance of a fizzler to link with its pair."""
    orig_target = begin_inst['targetname']

    if 'modelEnd' in orig_target:
        return  # We only execute starting from the start side.

    orig_target = orig_target[:-11]  # remove "_modelStart"
    end_name = orig_target + '_modelEnd'  # What we search for

    # The name all these instances get
    pair_name = orig_target + '-model' + str(begin_inst.id)

    orig_file = begin_inst['file']

    begin_file = res['StartInst', orig_file]
    end_file = res['EndInst', orig_file]
    mid_file = res['MidInst', '']

    begin_inst['file'] = begin_file
    begin_inst['targetname'] = pair_name

    angles = Vec.from_str(begin_inst['angles'])
    # We round it to get rid of 0.00001 inprecision from the calculations.
    direction = round(Vec(0, 0, 1).rotate(angles.x, angles.y, angles.z))
    ':type direction: utils.Vec'
    print(end_name, direction)

    begin_pos = Vec.from_str(begin_inst['origin'])
    axis_1, axis_2, main_axis = PAIR_AXES[direction.as_tuple()]
    for end_inst in VMF.by_class['func_instance']:
        if end_inst['targetname', ''] != end_name:
            # Only examine this barrier hazard's instances!
            continue
        end_pos = Vec.from_str(end_inst['origin'])
        if (
                begin_pos[axis_1] == end_pos[axis_1] and
                begin_pos[axis_2] == end_pos[axis_2]
                ):
            length = int(end_pos[main_axis] - begin_pos[main_axis])
            break
    else:
        utils.con_log('No matching pair for {}!!'.format(orig_target))
        return
    end_inst['targetname'] = pair_name
    end_inst['file'] = end_file

    if mid_file != '':
        # Go 64 from each side, and always have at least 1 section
        # A 128 gap will have length = 0
        for dis in range(0, abs(length) + 1, 128):
            new_pos = begin_pos + direction*dis
            VMF.create_ent(
                classname='func_instance',
                targetname=pair_name,
                angles=begin_inst['angles'],
                file=mid_file,
                origin=new_pos.join(' '),
            )
Esempio n. 6
0
def make_straight(
        origin: Vec,
        normal: Vec,
        dist: int,
        config: dict,
        is_start=False,
    ):
    """Make a straight line of instances from one point to another."""

    # 32 added to the other directions, plus extended dist in the direction
    # of the normal - 1
    p1 = origin + (normal * ((dist // 128 * 128) - 96))
    # The starting brush needs to
    # stick out a bit further, to cover the
    # point_push entity.
    p2 = origin - (normal * (96 if is_start else 32))

    # bbox before +- 32 to ensure the above doesn't wipe it out
    p1, p2 = Vec.bbox(p1, p2)

    solid = vbsp.VMF.make_prism(
        # Expand to 64x64 in the other two directions
        p1 - 32, p2 + 32,
        mat='tools/toolstrigger',
    ).solid

    motion_trigger(solid.copy())

    push_trigger(origin, normal, [solid])

    angles = normal.to_angle()

    support_file = config['support']
    straight_file = config['straight']
    support_positions = (
        SUPPORT_POS[normal.as_tuple()]
        if support_file else
        []
    )

    for off in range(0, int(dist), 128):
        position = origin + off * normal
        vbsp.VMF.create_ent(
            classname='func_instance',
            origin=position,
            angles=angles,
            file=straight_file,
        )

        for supp_ang, supp_off in support_positions:
            if (position + supp_off).as_tuple() in SOLIDS:
                vbsp.VMF.create_ent(
                    classname='func_instance',
                    origin=position,
                    angles=supp_ang,
                    file=support_file,
                )
Esempio n. 7
0
    def initialize(self):
        self.cloud_velocity = Vec(self.INIT_VELOCITY_X // 4, 0)
        self.gnd_velocity = Vec(self.INIT_VELOCITY_X,
                                0)  # same with enemy's velocity
        # cloud pos(list)
        self.cloud_pos = deepcopy(self.CLOUD_INIT_POS)

        # ground pos(list)
        self.gnd_pos = deepcopy(self.GND_INIT_POS)
Esempio n. 8
0
def res_fizzler_pair(begin_inst, res):
    """Modify the instance of a fizzler to link with its pair."""
    orig_target = begin_inst["targetname"]

    if "modelEnd" in orig_target:
        return  # We only execute starting from the start side.

    orig_target = orig_target[:-11]  # remove "_modelStart"
    end_name = orig_target + "_modelEnd"  # What we search for

    # The name all these instances get
    pair_name = orig_target + "-model" + str(begin_inst.id)

    orig_file = begin_inst["file"]

    begin_file = res["StartInst", orig_file]
    end_file = res["EndInst", orig_file]
    mid_file = res["MidInst", ""]

    begin_inst["file"] = begin_file
    begin_inst["targetname"] = pair_name

    angles = Vec.from_str(begin_inst["angles"])
    # We round it to get rid of 0.00001 inprecision from the calculations.
    direction = Vec(0, 0, 1).rotate(angles.x, angles.y, angles.z)
    ":type direction: utils.Vec"

    begin_pos = Vec.from_str(begin_inst["origin"])
    axis_1, axis_2, main_axis = PAIR_AXES[direction.as_tuple()]
    for end_inst in VMF.by_class["func_instance"]:
        if end_inst["targetname", ""] != end_name:
            # Only examine this barrier hazard's instances!
            continue
        end_pos = Vec.from_str(end_inst["origin"])
        if begin_pos[axis_1] == end_pos[axis_1] and begin_pos[axis_2] == end_pos[axis_2]:
            length = int(end_pos[main_axis] - begin_pos[main_axis])
            break
    else:
        utils.con_log("No matching pair for {}!!".format(orig_target))
        return
    end_inst["targetname"] = pair_name
    end_inst["file"] = end_file

    if mid_file != "":
        # Go 64 from each side, and always have at least 1 section
        # A 128 gap will have length = 0
        for dis in range(0, abs(length) + 1, 128):
            new_pos = begin_pos + direction * dis
            VMF.create_ent(
                classname="func_instance",
                targetname=pair_name,
                angles=begin_inst["angles"],
                file=mid_file,
                origin=new_pos.join(" "),
            )
Esempio n. 9
0
def res_unst_scaffold_setup(res):
    group = res["group", "DEFAULT_GROUP"]

    if group not in SCAFFOLD_CONFIGS:
        # Store our values in the CONFIGS dictionary
        targ_inst, links = SCAFFOLD_CONFIGS[group] = {}, {}
    else:
        # Grab the already-filled values, and add to them
        targ_inst, links = SCAFFOLD_CONFIGS[group]

    for block in res.find_all("Instance"):
        conf = {
            # If set, adjusts the offset appropriately
            "is_piston": utils.conv_bool(block["isPiston", "0"]),
            "rotate_logic": utils.conv_bool(block["AlterAng", "1"], True),
            "off_floor": Vec.from_str(block["FloorOff", "0 0 0"]),
            "off_wall": Vec.from_str(block["WallOff", "0 0 0"]),
            "logic_start": block["startlogic", ""],
            "logic_end": block["endLogic", ""],
            "logic_mid": block["midLogic", ""],
            "logic_start_rev": block["StartLogicRev", None],
            "logic_end_rev": block["EndLogicRev", None],
            "logic_mid_rev": block["EndLogicRev", None],
            "inst_wall": block["wallInst", ""],
            "inst_floor": block["floorInst", ""],
            "inst_offset": block["offsetInst", None],
            # Specially rotated to face the next track!
            "inst_end": block["endInst", None],
        }
        for logic_type in ("logic_start", "logic_mid", "logic_end"):
            if conf[logic_type + "_rev"] is None:
                conf[logic_type + "_rev"] = conf[logic_type]

        for inst in resolve_inst(block["file"]):
            targ_inst[inst] = conf

    # We need to provide vars to link the tracks and beams.
    for block in res.find_all("LinkEnt"):
        # The name for this set of entities.
        # It must be a '@' name, or the name will be fixed-up incorrectly!
        loc_name = block["name"]
        if not loc_name.startswith("@"):
            loc_name = "@" + loc_name
        links[block["nameVar"]] = {
            "name": loc_name,
            # The next entity (not set in end logic)
            "next": block["nextVar"],
            # A '*' name to reference all the ents (set on the start logic)
            "all": block["allVar", None],
        }

    return group  # We look up the group name to find the values.
Esempio n. 10
0
 def __init__(self, parent, position, size, length, direction):
     self.parent = parent
     self.position = position
     self.size = size
     self.length = length
     self.direction = direction
     # Set delta width and length vectors based on halleasy direction.
     if direction == dirs.E:
         self.dl = Vec(1, 0, 0)
         self.dw = Vec(0, 0, 1)
     else:
         self.dl = Vec(0, 0, 1)
         self.dw = Vec(1, 0, 0)
Esempio n. 11
0
def flag_goo_at_loc(inst, flag):
    """Check to see if a given location is submerged in goo.

    0 0 0 is the origin of the instance, values are in 128 increments.
    """
    pos = Vec.from_str(flag.value).rotate_by_str(inst['angles', '0 0 0'])
    pos *= 128
    pos += Vec.from_str(inst['origin'])

    # Round to 128 units, then offset to the center
    pos = pos // 128 * 128 + 64  # type: Vec
    val = pos.as_tuple() in GOO_LOCS
    return val
Esempio n. 12
0
 def updateVelAndIntrvl(self):
     # TODO: adjast the coefs
     dif = (Score.getScore() // 100)
     vel_x = self.INIT_VELOCITY_X - dif
     self.velocity = Vec(vel_x, 0)
     self.MIN_INTERVAL = 85 + 15 * dif
     self.MAX_INTERVAL = 150 + 15 * dif
Esempio n. 13
0
def track_scan(
        tr_set,
        track_inst,
        start_track: VLib.Entity,
        middle_file: str,
        x_dir: int,
        ):
    """Build a set of track instances extending from a point.
    :param track_inst: A dictionary mapping origins to track instances
    :param start_track: The instance we start on
    :param middle_file: The file for the center track piece
    :param x_dir: The direction to look (-1 or 1)
    """
    track = start_track
    move_dir = Vec(x_dir*128, 0, 0).rotate_by_str(track['angles'])
    while track:
        tr_set.add(track)

        next_pos = Vec.from_str(track['origin']) + move_dir
        track = track_inst.get(next_pos.as_tuple(), None)
        if track is None:
            return
        if track['file'].casefold() != middle_file:
            # If the next piece is an end section, add it then quit
            tr_set.add(track)
            return
Esempio n. 14
0
    def initialize(self):
        self.velocity = Vec(Enemy.INIT_VELOCITY_X, 0)
        interval = random.randrange(self.MIN_INTERVAL, self.MAX_INTERVAL)
        self.INIT_POS = [
            Vec(self.SPAWN_POS + i * self.MAX_INTERVAL + interval,
                self.GND_HEIGHT) for i in range(self.ENEMY_NUM)
        ]

        self.cur_anim = [None] * self.ENEMY_NUM
        self.pos = deepcopy(self.INIT_POS)
        # enemy is cactus or ptera
        for i in range(self.ENEMY_NUM):
            if random.random() < self.PTERA_SPAWN_RATIO:  # ptera
                self.cur_anim[i] = Enemy.PTERA_ANIMs[0]
                self.pos[i].y -= 40 * random.randrange(0, 2)
            else:  # big or small Cactus
                self.cur_anim[i] = Enemy.CACTUS_ANIMs[random.randrange(0, 2)]
Esempio n. 15
0
def flag_angles(inst, flag):
    """Check that a instance is pointed in a direction.

    The value should be either just the angle to check, or a block of
    options:
    - Angle: A unit vector (XYZ value) pointing in a direction, or some
        keywords: +z, -y, N/S/E/W, up/down, floor/ceiling, or walls
    - From_dir: The direction the unrotated instance is pointed in.
        This lets the flag check multiple directions
    - Allow_inverse: If true, this also returns True if the instance is
        pointed the opposite direction .
    """
    angle = inst['angles', '0 0 0']

    if flag.has_children():
        targ_angle = flag['direction', '0 0 0']
        from_dir = flag['from_dir', '0 0 1']
        if from_dir.casefold() in DIRECTIONS:
            from_dir = Vec(DIRECTIONS[from_dir.casefold()])
        else:
            from_dir = Vec.from_str(from_dir, 0, 0, 1)
        allow_inverse = utils.conv_bool(flag['allow_inverse', '0'])
    else:
        targ_angle = flag.value
        from_dir = Vec(0, 0, 1)
        allow_inverse = False

    if angle == targ_angle:
        return True  # Check for exact match

    normal = DIRECTIONS.get(targ_angle.casefold(), None)
    if normal is None:
        return False  # If it's not a special angle,
        # so it failed the exact match

    inst_normal = from_dir.rotate_by_str(angle)

    if normal == 'WALL':
        # Special case - it's not on the floor or ceiling
        return not (inst_normal == (0, 0, 1) or inst_normal == (0, 0, -1))
    else:
        return inst_normal == normal or (
            allow_inverse and -inst_normal == normal
        )
Esempio n. 16
0
def res_import_template_setup(res):
    temp_id = res['id'].casefold()

    face = Vec.from_str(res['face_pos', '0 0 -64'])
    norm = Vec.from_str(res['normal', '0 0 1'])

    replace_tex = defaultdict(list)
    for prop in res.find_key('replace', []):
        replace_tex[prop.name].append(prop.value)

    offset = Vec.from_str(res['offset', '0 0 0'])

    return (
        temp_id,
        dict(replace_tex),
        face,
        norm,
        offset,
    )
Esempio n. 17
0
def res_hollow_brush(inst, res):
    """Hollow out the attached brush, as if EmbeddedVoxel was set.

    This just removes the surface if it's already an embeddedVoxel. This allows
    multiple items to embed thinly in the same block without affecting each
    other.
    """
    loc = Vec(0, 0, -64).rotate_by_str(inst['angles'])
    loc += Vec.from_str(inst['origin'])

    try:
        group = SOLIDS[loc.as_tuple()]
    except KeyError:
        LOGGER.warning('No brush for hollowing at ({})', loc)
        return  # No brush here?

    conditions.hollow_block(
        group,
        remove_orig_face=utils.conv_bool(res['RemoveFace', False])
    )
Esempio n. 18
0
 def apply_template(self, tmpl, cmds, mat, reps, pos):
     '''
     Apply a template.
     tmpl = the actual template
     mat = materials lookup
     reps for each template row
     pos = starting position
     '''
     for l in xrange(len(tmpl[0])):
         for rl in xrange(reps['l'][l]):
             for d in xrange(len(tmpl)):
                 repw = 0
                 for w in xrange(len(tmpl[d][l])):
                     for rw in xrange(reps['w'][w]):
                         q = pos + self.dw * repw \
                                 + Vec(0, -1, 0) * d
                         repw += 1
                         if tmpl[d][l][w] == 'XX':
                             continue
                         elif tmpl[d][l][w] == '~T':
                             if random.randint(1, 100) <= 90:
                                 self.parent.setblock(
                                     q,
                                     materials.RedstoneWire,
                                     hide=True
                                 )
                             else:
                                 self.parent.setblock(
                                     q,
                                     materials.TNT,
                                     hide=True
                                 )
                             continue
                         elif (
                             tmpl[d][l][w][0] == '~' and
                             random.randint(1, 100) <= 50
                         ):
                             continue
                         self.parent.setblock(
                             q,
                             mat[tmpl[d][l][w]][0],
                             mat[tmpl[d][l][w]][1],
                             hide=True
                         )
                         if tmpl[d][l][w] in cmds:
                             self.parent.addtileentity(
                                 get_tile_entity_tags(
                                     eid='Control',
                                     Pos=q,
                                     Command=cmds[tmpl[d][l][w]]
                                 )
                             )
             pos += self.dl
Esempio n. 19
0
def flag_angles(inst, flag):
    """Check that a instance is pointed in a direction."""
    angle = inst["angles", "0 0 0"]

    if flag.has_children():
        targ_angle = flag["direction", "0 0 0"]
        from_dir = flag["from_dir", "0 0 1"]
        if from_dir.casefold() in DIRECTIONS:
            from_dir = Vec(DIRECTIONS[from_dir.casefold()])
        else:
            from_dir = Vec.from_str(from_dir, 0, 0, 1)
        allow_inverse = utils.conv_bool(flag["allow_inverse", "0"])
    else:
        targ_angle = flag.value
        from_dir = Vec(0, 0, 1)
        allow_inverse = False

    if angle == targ_angle:
        return True  # Check for exact match

    normal = DIRECTIONS.get(targ_angle.casefold(), None)
    if normal is None:
        return False  # If it's not a special angle,
        # so it failed the exact match

    angle = Vec.from_str(angle, 0, 0, 0)
    inst_normal = from_dir.rotate(angle.x, angle.y, angle.z)

    if normal == "WALL":
        # Special case - it's not on the floor or ceiling
        return not (inst_normal == (0, 0, 1) or inst_normal == (0, 0, -1))
    else:
        return inst_normal == normal or (allow_inverse and -inst_normal == normal)
Esempio n. 20
0
def join_markers(inst_a, inst_b, is_start=False):
    """Join two marker ents together with corners.

    This returns a list of solids used for the vphysics_motion trigger.
    """
    origin_a = Vec.from_str(inst_a['ent']['origin'])
    origin_b = Vec.from_str(inst_b['ent']['origin'])

    norm_a = Vec(-1, 0, 0).rotate_by_str(inst_a['ent']['angles'])
    norm_b = Vec(-1, 0, 0).rotate_by_str(inst_b['ent']['angles'])

    config = inst_a['conf']

    if norm_a == norm_b:
        # Either straight-line, or s-bend.
        dist = (origin_a - origin_b).mag()

        if origin_a + (norm_a * dist) == origin_b:
            make_straight(
                origin_a,
                norm_a,
                dist,
                config,
                is_start,
            )
        # else: S-bend, we don't do the geometry for this..
        return

    if norm_a == -norm_b:
        # U-shape bend..
        make_ubend(
            origin_a,
            origin_b,
            norm_a,
            config,
            max_size=inst_a['size'],
        )
        return

    try:
        corner_ang, flat_angle = CORNER_ANG[norm_a.as_tuple(), norm_b.as_tuple()]

        if origin_a[flat_angle] != origin_b[flat_angle]:
            # It needs to be flat in this angle!
            raise ValueError
    except ValueError:
        # The tubes need two corners to join together - abort for that.
        return
    else:
        make_bend(
            origin_a,
            origin_b,
            norm_a,
            norm_b,
            corner_ang,
            config,
            max_size=inst_a['size'],
        )
Esempio n. 21
0
def find_indicator_panels(inst):
    """We need to locate indicator panels, so they aren't overwritten.
    """
    if inst['file'].casefold() not in resolve_inst('[indpan]'):
        return
    loc = Vec(0, 0, -64).rotate_by_str(inst['angles'])
    loc += Vec.from_str(inst['origin'])

    # Sometimes (light bridges etc) a sign will be halfway between
    # tiles, so in that case we need to force 2 tiles.
    loc_min = (loc - (15, 15, 0)) // 32 * 32 + (16, 16, 0)
    loc_max = (loc + (15, 15, 0)) // 32 * 32 + (16, 16, 0)
    FORCE_LOCATIONS.add(loc_min.as_tuple())
    FORCE_LOCATIONS.add(loc_max.as_tuple())
Esempio n. 22
0
def res_translate_inst(inst, res):
    """Translate the instance locally by the given amount.

    The special values <piston>, <piston_bottom> and <piston_top> can be
    used to offset it based on the starting position, bottom or top position
    of a piston platform.
    """
    folded_val = res.value.casefold()
    if folded_val == '<piston>':
        folded_val = (
            '<piston_top>' if
            utils.conv_bool(inst.fixup['$start_up'])
            else '<piston_bottom>'
        )

    if folded_val == '<piston_top>':
        val = Vec(z=128 * utils.conv_int(inst.fixup['$top_level', '1'], 1))
    elif folded_val == '<piston_bottom>':
        val = Vec(z=128 * utils.conv_int(inst.fixup['$bottom_level', '0'], 0))
    else:
        val = Vec.from_str(res.value)

    offset = val.rotate_by_str(inst['angles'])
    inst['origin'] = (offset + Vec.from_str(inst['origin'])).join(' ')
Esempio n. 23
0
    def update(self):
        if Player.getState() == "IDLE":
            return
        # update velocity, pos
        self.updateVel()
        if pyxel.frame_count % 2:
            for i in range(len(self.cloud_pos)):
                self.cloud_pos[i] = Vec(
                    self.cloud_pos[i].x + self.cloud_velocity.x,
                    self.cloud_pos[i].y)
            for i in range(len(self.gnd_pos)):
                self.gnd_pos[i] = Vec(self.gnd_pos[i].x + self.gnd_velocity.x,
                                      self.gnd_pos[i].y)

        # 左端についたら右端に戻す
        # lastに合わせて距離を保つ
        for i in range(len(self.cloud_pos)):
            if self.cloud_pos[i].x < -50:
                self.cloud_pos[i] = Vec(self.CLOUD_INIT_POS[-1].x,
                                        self.cloud_pos[i].y)
        for i in range(len(self.gnd_pos)):
            if self.gnd_pos[i].x < -120:
                self.gnd_pos[i] = Vec(self.GND_INIT_POS[-1].x,
                                      self.gnd_pos[i].y)
Esempio n. 24
0
def color_square(color: utils.Vec, size=16):
    """Create a square image of the given size, with the given color."""
    key = color.x, color.y, color.z, size

    try:
        return cached_squares[key]
    except KeyError:
        img = Image.new(
            mode='RGB',
            size=(size, size),
            color=(int(color.x), int(color.y), int(color.z)),
        )
        tk_img = ImageTk.PhotoImage(image=img)
        cached_squares[color.as_tuple(), size] = tk_img

        return tk_img
Esempio n. 25
0
def res_faith_mods(inst, res):
    """Modify the trigger_catrapult that is created for ItemFaithPlate items.

    Values:
        - raise_trig: Raise or lower the trigger_catapults by this amount.
        - angled_targ, angled_in: Instance entity and input for angled plates
        - straight_targ, straight_in: Instance entity and input for
            straight plates
        - instvar: A $replace value to set to either 'angled' or '
            'straight'.
    """
    # Get data about the trigger this instance uses for flinging
    fixup_var = res['instvar', '']
    offset = utils.conv_int(res['raise_trig', '0'])
    if offset:
        offset = Vec(0, 0, offset).rotate_by_str(inst['angles', '0 0 0'])
        ':type offset Vec'
    for trig in vbsp.VMF.by_class['trigger_catapult']:
        if inst['targetname'] in trig['targetname']:
            if offset:  # Edit both the normal and the helper trigger
                trig['origin'] = (
                    Vec.from_str(trig['origin']) +
                    offset
                ).join(' ')
                for solid in trig.solids:
                    solid.translate(offset)

            # Inspect the outputs to determine the type.
            # We also change them if desired, since that's not possible
            # otherwise.

            for out in trig.outputs:
                if out.inst_in == 'animate_angled_relay':
                    out.inst_in = res['angled_targ', 'animate_angled_relay']
                    out.input = res['angled_in', 'Trigger']
                    if fixup_var:
                        inst.fixup[fixup_var] = 'angled'
                    break # There's only one output we want to look for...
                elif out.inst_in == 'animate_straightup_relay':
                    out.inst_in = res[
                        'straight_targ', 'animate_straightup_relay'
                    ]
                    out.input = res['straight_in', 'Trigger']
                    if fixup_var:
                        inst.fixup[fixup_var] = 'straight'
                    break
Esempio n. 26
0
def res_import_template_setup(res):
    temp_id = res['id'].casefold()

    force = res['force', ''].casefold().split()
    if 'white' in force:
        force_colour = MAT_TYPES.white
    elif 'black' in force:
        force_colour = MAT_TYPES.black
    elif 'invert' in force:
        force_colour = 'INVERT'
    else:
        force_colour = None

    if 'world' in force:
        force_type = TEMP_TYPES.world
    elif 'detail' in force:
        force_type = TEMP_TYPES.detail
    else:
        force_type = TEMP_TYPES.default

    for size in ('2x2', '4x4', 'wall', 'special'):
        if size in force:
            force_grid = size
            break
    else:
        force_grid = None

    replace_tex = defaultdict(list)
    for prop in res.find_key('replace', []):
        replace_tex[prop.name].append(prop.value)

    replace_brush = res['replaceBrush', None]
    if replace_brush:
        replace_brush_pos = Vec.from_str(replace_brush)
        replace_brush_pos.z -= 64  # 0 0 0 defaults to the floor.
    else:
        replace_brush_pos = None

    return (
        temp_id,
        dict(replace_tex),
        force_colour,
        force_grid,
        force_type,
        replace_brush_pos,
    )
Esempio n. 27
0
def make_corner(origin, angle, size, config):
    vbsp.VMF.create_ent(
        classname='func_instance',
        origin=origin,
        angles=angle,
        file=config['corner', size],
    )

    temp = config['corner_temp', size]
    if temp:
        temp_solids = import_template(
            temp,
            origin=origin,
            angles=Vec.from_str(angle),
            force_type=TEMP_TYPES.world,
        ).world
        for solid in temp_solids:
            vbsp.VMF.remove_brush(solid)
        motion_trigger(*temp_solids)
Esempio n. 28
0
def make_vac_track(start, all_markers):
    """Create a vactube path section.

    """

    start_normal = Vec(-1, 0, 0).rotate_by_str(start['ent']['angles'])

    # First create the start section..
    start_logic = start['ent'].copy()
    vbsp.VMF.add_ent(start_logic)

    start_logic['file'] = start['conf']['entry', (
        'ceiling' if (start_normal.z > 0) else
        'floor' if (start_normal.z < 0) else
        'wall'
    )]

    end = start

    for inst, end in follow_vac_path(all_markers, start):
        join_markers(inst, end, inst is start)

    end_loc = Vec.from_str(end['ent']['origin'])
    end_norm = Vec(-1, 0, 0).rotate_by_str(end['ent']['angles'])

    # join_markers creates straight parts up-to the marker, but not at it's
    # location - create the last one.
    make_straight(
        end_loc,
        end_norm,
        128,
        end['conf'],
    )

    # If the end is placed in goo, don't add logic - it isn't visible, and
    # the object is on a one-way trip anyway.
    if end_loc.as_tuple() not in GOO_LOCS:
        end_logic = end['ent'].copy()
        vbsp.VMF.add_ent(end_logic)
        end_logic['file'] = end['conf']['exit']
Esempio n. 29
0
    def render(self):
        if (utils.sum_points_inside_flat_poly(*self.parent.canvas) <= 4):
            return
        color_profile = random.choice(self.colors)

        min_x = utils.floor(min([p.x for p in self.parent.canvas]))
        max_x = utils.ceil(max([p.x for p in self.parent.canvas]))
        min_z = utils.floor(min([p.z for p in self.parent.canvas]))
        max_z = utils.ceil(max([p.z for p in self.parent.canvas]))
        min_y = utils.floor(min([p.y for p in self.parent.canvas]))

        # Cut the canvas into quarters and fill one quarter with colors.
        # Then, copy that quarter into the other three quarters.
        width = utils.floor(((max_x - min_x + 1) + 1) / 2)
        depth = utils.floor(((max_z - min_z + 1) + 1) / 2)

        points = [[-1 for j in xrange(depth)] for i in xrange(width)]
        points_left = []
        for i in xrange(width):
            for j in xrange(depth):
                points_left.append((i, j))
        bounds = utils.Box(Vec(0, 0, 0), width, 1, depth)
        p = Vec(0, 0, 0)
        color_num = 0
        prev_dir = random.randint(0, 3)
        next_dir = random.randint(0, 3)
        while len(points_left) > 0:
            # pick random starting point and walk around the matrix
            point_index = random.randint(0, len(points_left) - 1)
            p = Vec(points_left[point_index][0], 0,
                    points_left[point_index][1])

            while (bounds.containsPoint(p) and points[p.x][p.z] == -1
                   and len(points_left) > 0):
                points[p.x][p.z] = color_num
                points_left.remove((p.x, p.z))

                # pick random direction to walk, try to keep walking same
                # direction
                if random.randint(0, self._walk_weight) != 0:
                    next_dir = prev_dir
                else:
                    while next_dir == prev_dir:
                        next_dir = random.randint(0, 3)
                if next_dir == 0:  # right
                    p += Vec(1, 0, 0)
                elif next_dir == 1:  # down
                    p += Vec(0, 0, 1)
                elif next_dir == 2:  # left
                    p += Vec(-1, 0, 0)
                else:  # up
                    p += Vec(0, 0, -1)
                prev_dir = next_dir
            color_num = (color_num + 1) % len(color_profile)

        for j in xrange(max_z - min_z + 1):
            for i in xrange(max_x - min_x + 1):
                p = self.parent.loc + Vec(min_x + i, min_y, min_z + j)
                self.parent.parent.setblock(p, self.mat)
                if i < width:
                    i_adj = i
                else:
                    i_adj = 2 * width - 1 - i
                if j < depth:
                    j_adj = j
                else:
                    j_adj = 2 * depth - 1 - j
                self.parent.parent.blocks[p].data = \
                    color_profile[points[i_adj][j_adj]]

        if not self.ruin:
            return
        # this chunk of code is copied from CheckerRug's render() method
        pn = perlin.SimplexNoise(256)
        c = self.parent.canvasCenter()
        y = self.parent.canvasHeight()
        r = random.randint(1, 1000)
        maxd = max(1, self.parent.canvasWidth(), self.parent.canvasLength())
        for x in utils.iterate_points_inside_flat_poly(*self.parent.canvas):
            p = x + self.parent.loc
            d = ((Vec2f(x.x, x.z) - c).mag()) / maxd
            n = (pn.noise3((p.x + r) / 4.0, y / 4.0, p.z / 4.0) + 1.0) / 2.0
            if (n < d):
                self.parent.parent.setblock(p, materials._floor)
                self.parent.parent.blocks[p].data = 0
Esempio n. 30
0
def res_fix_rotation_axis(ent, res):
    """Generate a `func_rotating`, `func_door_rotating` or any similar entity.

    This uses the orientation of the instance to detemine the correct
    spawnflags to make it rotate in the correct direction. The brush
    will be 2x2x2 units large, and always set to be non-solid.
    - `Pos` and `name` are local to the
      instance, and will set the `origin` and `targetname` respectively.
    - `Keys` are any other keyvalues to be be set.
    - `Flags` sets additional spawnflags. Multiple values may be
       separated by '+', and will be added together.
    - `Classname` specifies which entity will be created, as well as
       which other values will be set to specify the correct orientation.
    - `AddOut` is used to add outputs to the generated entity. It takes
       the options `Output`, `Target`, `Input`, `Param` and `Delay`. If
       `Inst_targ` is defined, it will be used with the input to construct
       an instance proxy input. If `OnceOnly` is set, the output will be
       deleted when fired.

    Permitted entities:
     * `func_rotating`
     * `func_door_rotating`
     * `func_rot_button`
     * `func_platrot`
    """
    des_axis = res['axis', 'z'].casefold()
    reverse = utils.conv_bool(res['reversed', '0'])
    door_type = res['classname', 'func_door_rotating']

    # Extra stuff to apply to the flags (USE, toggle, etc)
    flags = sum(map(
        # Add together multiple values
        utils.conv_int,
        res['flags', '0'].split('+')
    ))

    name = res['name', '']
    if not name.startswith('@'):
        # If a local name is given, add it to the instance targetname.
        # It the name given is '', set to the instance's name.
        # If it has an @, don't change it!
        name = ent['targetname', ''] + (('-' + name) if name else '')

    axis = Vec(
        x=int(des_axis == 'x'),
        y=int(des_axis == 'y'),
        z=int(des_axis == 'z'),
    ).rotate_by_str(ent['angles', '0 0 0'])

    pos = Vec.from_str(
        res['Pos', '0 0 0']
    ).rotate_by_str(ent['angles', '0 0 0'])
    pos += Vec.from_str(ent['origin', '0 0 0'])

    door_ent = vbsp.VMF.create_ent(
        classname=door_type,
        targetname=name,
        origin=pos.join(' '),
    )

    conditions.set_ent_keys(door_ent, ent, res)

    for output in res.find_all('AddOut'):
        door_ent.add_out(VLib.Output(
            out=output['Output', 'OnUse'],
            inp=output['Input', 'Use'],
            targ=output['Target', ''],
            inst_in=output['Inst_targ', None],
            param=output['Param', ''],
            delay=utils.conv_float(output['Delay', '']),
            times=(
                1 if
                utils.conv_bool(output['OnceOnly', False])
                else -1),
        ))

    # Generate brush
    door_ent.solids = [vbsp.VMF.make_prism(pos - 1, pos + 1).solid]

    if axis.x > 0 or axis.y > 0 or axis.z > 0:
        # If it points forward, we need to reverse the rotating door
        reverse = not reverse

    flag_values = FLAG_ROTATING[door_type]
    # Make the door always non-solid!
    flags |= flag_values.get('solid_flags', 0)
    # Add or remove flags as needed.
    # flags |= bit sets it to 1.
    # flags |= ~bit sets it to 0.
    if axis.x != 0:
        flags |= flag_values.get('x', 0)
    else:
        flags &= ~flag_values.get('x', 0)

    if axis.y != 0:
        flags |= flag_values.get('y', 0)
    else:
        flags &= ~flag_values.get('y', 0)

    if axis.z != 0:
        flags |= flag_values.get('z', 0)
    else:
        flags &= ~flag_values.get('z', 0)

    if door_type == 'momentary_rot_button':
        door_ent['startdirection'] = '1' if reverse else '-1'
    else:
        if reverse:
            flags |= flag_values.get('rev', 0)
        else:
            flags &= ~flag_values.get('rev', 0)
    door_ent['spawnflags'] = str(flags)
Esempio n. 31
0
 def updateVel(self):
     # TODO: adjast the coefs
     dif = (Score.getScore() // 100)
     vel_x = self.INIT_VELOCITY_X - dif
     self.velocity = Vec(vel_x, 0)
Esempio n. 32
0
def res_import_template(inst, res):
    """Import a template VMF file, retexturing it to match orientatation.

    It will be placed overlapping the given instance.
    Options:
    - ID: The ID of the template to be inserted.
    - force: a space-seperated list of overrides. If 'white' or 'black' is
             present, the colour of tiles will be overriden. If a tile size
            ('2x2', '4x4', 'wall', 'special') is included, all tiles will
            be switched to that size (if not a floor/ceiling). If 'world' or
            'detail' is present, the brush will be forced to that type.
    - replace: A block of template material -> replacement textures.
            This is case insensitive - any texture here will not be altered
            otherwise.
    - replaceBrush: The position of a brush to replace (0 0 0=the surface).
            This brush will be removed, and overlays will be fixed to use
            all faces with the same normal.
    """
    (
        temp_id,
        replace_tex,
        force_colour,
        force_grid,
        force_type,
        replace_brush_pos,
    ) = res.value

    if temp_id not in TEMPLATES:
        # The template map is read in after setup is performed, so
        # it must be checked here!
        # We don't want an error, just quit
        LOGGER.warning('"{}" not a valid template!', temp_id)
        return

    origin = Vec.from_str(inst['origin'])
    angles = Vec.from_str(inst['angles', '0 0 0'])
    temp_data = conditions.import_template(
        temp_id,
        origin,
        angles,
        targetname=inst['targetname', ''],
        force_type=force_type,
    )
    conditions.retexture_template(
        temp_data,
        origin,
        replace_tex,
        force_colour,
        force_grid,
    )

    # This is the original brush the template is replacing. We fix overlay
    # face IDs, so this brush is replaced by the faces in the template pointing
    # the same way.
    if replace_brush_pos is None:
        return

    pos = Vec(replace_brush_pos).rotate(angles.x, angles.y, angles.z)
    pos += origin

    try:
        brush_group = SOLIDS[pos.as_tuple()]
    except KeyError:
        return

    vbsp.VMF.remove_brush(brush_group.solid)
    new_ids = []

    all_brushes = temp_data.world
    if temp_data.detail is not None:
        for ent in temp_data.detail:
            all_brushes.extend(ent.solids)

    for brush in all_brushes:  # type: VLib.Solid
        for face in brush.sides:
            # Only faces pointing the same way!
            if face.normal() == brush_group.normal:
                # Skip tool brushes (nodraw, player clips..)
                if face.mat.casefold().startswith('tools/'):
                    continue
                new_ids.append(str(face.id))

    if new_ids:
        conditions.reallocate_overlays({
            str(brush_group.face.id): new_ids,
        })
Esempio n. 33
0
def res_add_brush(inst, res):
    """Spawn in a brush at the indicated points.

    - point1 and point2 are locations local to the instance, with '0 0 0'
      as the floor-position.
    - type is either 'black' or 'white'.
    - detail should be set to True/False. If true the brush will be a
      func_detail instead of a world brush.

    The sides will be textured with 1x1, 2x2 or 4x4 wall, ceiling and floor
    textures as needed.
    """
    import vbsp

    point1 = Vec.from_str(res['point1'])
    point2 = Vec.from_str(res['point2'])

    point1.z -= 64  # Offset to the location of the floor
    point2.z -= 64

    # Rotate to match the instance
    point1.rotate_by_str(inst['angles'])
    point2.rotate_by_str(inst['angles'])

    origin = Vec.from_str(inst['origin'])
    point1 += origin  # Then offset to the location of the instance
    point2 += origin

    tex_type = res['type', None]
    if tex_type not in ('white', 'black'):
        LOGGER.warning(
            'AddBrush: "{}" is not a valid brush '
            'color! (white or black)',
            tex_type,
        )
        tex_type = 'black'

    dim = point2 - point1
    dim.max(-dim)

    # Figure out what grid size and scale is needed
    # Check the dimensions in two axes to figure out the largest
    # tile size that can fit in it.
    x_maxsize = min(dim.y, dim.z)
    y_maxsize = min(dim.x, dim.z)
    if x_maxsize <= 32:
        x_grid = '4x4'
    elif x_maxsize <= 64:
        x_grid = '2x2'
    else:
        x_grid = 'wall'

    if y_maxsize <= 32:
        y_grid = '4x4'
    elif y_maxsize <= 64:
        y_grid = '2x2'
    else:
        y_grid = 'wall'

    grid_offset = origin // 128  # type: Vec

    # All brushes in each grid have the same textures for each side.
    random.seed(grid_offset.join(' ') + '-partial_block')

    solids = vbsp.VMF.make_prism(point1, point2)
    ':type solids: VLib.PrismFace'

    # Ensure the faces aren't re-textured later
    vbsp.IGNORED_FACES.update(solids.solid.sides)

    solids.north.mat = vbsp.get_tex(tex_type + '.' + y_grid)
    solids.south.mat = vbsp.get_tex(tex_type + '.' + y_grid)
    solids.east.mat = vbsp.get_tex(tex_type + '.' + x_grid)
    solids.west.mat = vbsp.get_tex(tex_type + '.' + x_grid)
    solids.top.mat = vbsp.get_tex(tex_type + '.floor')
    solids.bottom.mat = vbsp.get_tex(tex_type + '.ceiling')

    if utils.conv_bool(res['detail', False], False):
        # Add the brush to a func_detail entity
        vbsp.VMF.create_ent(
            classname='func_detail'
        ).solids = [
            solids.solid
        ]
    else:
        # Add to the world
        vbsp.VMF.add_brush(solids.solid)
Esempio n. 34
0
def res_set_texture(inst, res):
    """Set the brush face at a location to a particular texture.

    pos is the position, relative to the instance
      (0 0 0 is the floor-surface).
    dir is the normal of the texture.
    If gridPos is true, the position will be snapped so it aligns with
     the 128 brushes (Useful with fizzler/light strip items).

    tex is the texture used.
    If tex begins and ends with '<>', certain
    textures will be used based on style:
    - If tex is '<special>', the brush will be given a special texture
      like angled and clear panels.
    - '<white>' and '<black>' will use the regular textures for the
      given color.
    - '<white-2x2>', '<white-4x4>', '<black-2x2>', '<black-4x4'> will use
      the given wall-sizes. If on floors or ceilings these always use 4x4.
    - '<2x2>' or '<4x4>' will force to the given wall-size, keeping color.
    - '<special-white>' and '<special-black>' will use a special texture
       of the given color.
    If tex begins and ends with '[]', it is an option in the 'Textures' list.
    These are composed of a group and texture, separated by '.'. 'white.wall'
    are the white wall textures; 'special.goo' is the goo texture.
    """
    import vbsp
    pos = Vec.from_str(res['pos', '0 0 0'])
    pos.z -= 64  # Subtract so origin is the floor-position
    pos = pos.rotate_by_str(inst['angles', '0 0 0'])

    # Relative to the instance origin
    pos += Vec.from_str(inst['origin', '0 0 0'])

    norm = Vec.from_str(res['dir', '0 0 -1']).rotate_by_str(
        inst['angles', '0 0 0']
    )

    if utils.conv_bool(res['gridpos', '0']):
        for axis in 'xyz':
            # Don't realign things in the normal's axis -
            # those are already fine.
            if not norm[axis]:
                pos[axis] //= 128
                pos[axis] *= 128
                pos[axis] += 64

    brush = SOLIDS.get(pos.as_tuple(), None)
    ':type brush: solidGroup'

    if not brush or brush.normal != norm:
        return

    tex = res['tex']

    if tex.startswith('[') and tex.endswith(']'):
        brush.face.mat = vbsp.get_tex(tex[1:-1])
        brush.face.mat = tex
    elif tex.startswith('<') and tex.endswith('>'):
        # Special texture names!
        tex = tex[1:-1].casefold()
        if tex == 'white':
            brush.face.mat = 'tile/white_wall_tile003a'
        elif tex == 'black':
            brush.face.mat = 'metal/black_wall_metal_002c'

        if tex == 'black' or tex == 'white':
            # For these two, run the regular logic to apply textures
            # correctly.
            vbsp.alter_mat(
                brush.face,
                vbsp.face_seed(brush.face),
                vbsp.get_bool_opt('tile_texture_lock', True),
            )

        if tex == 'special':
            vbsp.set_special_mat(brush.face, str(brush.color))
        elif tex == 'special-white':
            vbsp.set_special_mat(brush.face, 'white')
            return
        elif tex == 'special-black':
            vbsp.set_special_mat(brush.face, 'black')

        # Do <4x4>, <white-2x4>, etc
        color = str(brush.color)
        if tex.startswith('black') or tex.endswith('white'):
            # Override the color used for 2x2/4x4 brushes
            color = tex[:5]
        if tex.endswith('2x2') or tex.endswith('4x4'):
            # 4x4 and 2x2 instructions are ignored on floors and ceilings.
            orient = vbsp.get_face_orient(brush.face)
            if orient == vbsp.ORIENT.wall:
                brush.face.mat = vbsp.get_tex(
                    color + '.' + tex[-3:]
                )
            else:
                brush.face.mat = vbsp.get_tex(
                    color + '.' + str(orient)
                )
    else:
        brush.face.mat = tex

    # Don't allow this to get overwritten later.
    vbsp.IGNORED_FACES.add(brush.face)
Esempio n. 35
0
    def render(self):
        if (utils.sum_points_inside_flat_poly(*self.parent.canvas) <= 4):
            return
        color_profile = random.choice(self.colors)

        min_x = utils.floor(min([p.x for p in self.parent.canvas]))
        max_x = utils.ceil(max([p.x for p in self.parent.canvas]))
        min_z = utils.floor(min([p.z for p in self.parent.canvas]))
        max_z = utils.ceil(max([p.z for p in self.parent.canvas]))
        min_y = utils.floor(min([p.y for p in self.parent.canvas]))

        # Cut the canvas into quarters and fill one quarter with colors.
        # Then, copy that quarter into the other three quarters.
        width = utils.floor(((max_x - min_x + 1) + 1) / 2)
        depth = utils.floor(((max_z - min_z + 1) + 1) / 2)

        points = [[-1 for j in xrange(depth)] for i in xrange(width)]
        points_left = []
        for i in xrange(width):
            for j in xrange(depth):
                points_left.append((i, j))
        bounds = utils.Box(Vec(0, 0, 0), width, 1, depth)
        p = Vec(0, 0, 0)
        color_num = 0
        prev_dir = random.randint(0, 3)
        next_dir = random.randint(0, 3)
        while len(points_left) > 0:
            # pick random starting point and walk around the matrix
            point_index = random.randint(0, len(points_left) - 1)
            p = Vec(points_left[point_index][0], 0,
                    points_left[point_index][1])

            while (bounds.containsPoint(p) and points[p.x][p.z] == -1
                   and len(points_left) > 0):
                points[p.x][p.z] = color_num
                points_left.remove((p.x, p.z))

                # pick random direction to walk, try to keep walking same
                # direction
                if random.randint(0, self._walk_weight) != 0:
                    next_dir = prev_dir
                else:
                    while next_dir == prev_dir:
                        next_dir = random.randint(0, 3)
                if next_dir == 0:  # right
                    p += Vec(1, 0, 0)
                elif next_dir == 1:  # down
                    p += Vec(0, 0, 1)
                elif next_dir == 2:  # left
                    p += Vec(-1, 0, 0)
                else:  # up
                    p += Vec(0, 0, -1)
                prev_dir = next_dir
            color_num = (color_num + 1) % len(color_profile)

        for j in xrange(max_z - min_z + 1):
            for i in xrange(max_x - min_x + 1):
                p = self.parent.loc + Vec(min_x + i, min_y, min_z + j)
                self.parent.parent.setblock(p, self.mat)
                if i < width:
                    i_adj = i
                else:
                    i_adj = 2 * width - 1 - i
                if j < depth:
                    j_adj = j
                else:
                    j_adj = 2 * depth - 1 - j
                self.parent.parent.blocks[p].data = \
                    color_profile[points[i_adj][j_adj]]
        # Ruined
        if (self.ruin):
            self.ruinrender()
Esempio n. 36
0
    def generate_map(self, dungeon, level):
        '''Generate a new map, save it to disk, flush the cache, and return a
        map item NBT with the appropriate map ID.'''

        dungeon_key = '%s,%s' % (dungeon.position.x, dungeon.position.z)
        if dungeon_key not in self.mapcache['used']:
            self.mapcache['used'][dungeon_key] = set([])

        # Find a map id. Look in the available list for old mcdungeon maps
        # that can be reused. If not, bump up the idcount and use that.
        if len(self.mapcache['available']) == 0:
            # Initialize the map count if it doesn't exist.
            if 'map' not in self.idcounts:
                self.idcounts['map'] = nbt.TAG_Short(-1)

            self.idcounts['map'].value += 1
            mapid = self.idcounts['map'].value
            self.mapcache['used'][dungeon_key].add(mapid)
        else:
            mapid = self.mapcache['available'].pop()
            self.mapcache['used'][dungeon_key].add(mapid)
        filename = os.path.join(self.mapstore, 'map_%d.dat' % (mapid))

        # Setup the defaults.
        # Offset will be way off somewhere were players are unlikely to go
        # to avoid the maps from being overwritten. Nothing else really
        # matters.
        tags = nbt.TAG_Compound()
        tags['data'] = nbt.TAG_Compound()
        tags['data']['scale'] = nbt.TAG_Byte(0)
        tags['data']['xCenter'] = nbt.TAG_Int(-12500000)
        tags['data']['zCenter'] = nbt.TAG_Int(-12500000)
        tags['data']['height'] = nbt.TAG_Short(128)
        tags['data']['width'] = nbt.TAG_Short(128)
        tags['data']['dimension'] = nbt.TAG_Byte(0)
        tags['data']['colors'] = nbt.TAG_Byte_Array(zeros(16384, uint8))

        # Generate the map.
        blocks = dungeon.blocks
        colors = tags['data']['colors'].value
        y = level * dungeon.room_height - 3
        # Scale the map. We only scale up, not down since scaling
        # looks terrible.
        max_dungeon = max(dungeon.xsize * dungeon.room_size,
                          dungeon.zsize * dungeon.room_size)
        max_dungeon = max(128, max_dungeon)

        # If the size is less than 8, try to center it.
        xoffset = 0
        zoffset = 0
        if dungeon.xsize * dungeon.room_size < 128:
            xoffset = (128 - dungeon.xsize * dungeon.room_size) / 2
        if dungeon.zsize * dungeon.room_size < 128:
            zoffset = (128 - dungeon.zsize * dungeon.room_size) / 2

        # Draw pixels on the map corresponding to blocks just above
        # floor level. Color chests and spawners. Hide things that should be
        # hidden.
        for x in xrange(128):
            for z in xrange(128):
                block = Vec(x * max_dungeon / 128 - xoffset, y,
                            z * max_dungeon / 128 - zoffset)
                if block in blocks:
                    mat = blocks[block].material
                    if mat == materials.StonePressurePlate:
                        colors[x + z * 128] = 10
                    elif blocks[block].hide is True:
                        colors[x + z * 128] = 0
                    elif blocks[block].blank is True:
                        colors[x + z * 128] = 0
                    elif mat == materials.Air:
                        colors[x + z * 128] = 10
                    elif mat == materials.Spawner:
                        colors[x + z * 128] = 48
                    elif (mat == materials.Chest
                          or mat == materials.TrappedChest):
                        colors[x + z * 128] = 42
                    else:
                        colors[x + z * 128] = 54
                else:
                    colors[x + z * 128] = 0

        # Draw the level number in the corner
        digits = [[0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0],
                  [0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1],
                  [1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1],
                  [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0],
                  [1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1],
                  [1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1],
                  [0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1],
                  [1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0],
                  [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1],
                  [1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1]]
        sx = 120
        if level < 10:
            sx = 124
        sz = 123
        for d in str(level):
            for x in xrange(3):
                for z in xrange(5):
                    if digits[int(d)][x + z * 3] == 1:
                        colors[x + sx + (z + sz) * 128] = 16
            sx += 4

        # Save the map file, cache, and idcount.dat
        tags.save(filename)
        self.update_mapstore()

        # Return a map item
        item = nbt.TAG_Compound()
        item['id'] = nbt.TAG_String(items.byName('map').id)
        item['Damage'] = nbt.TAG_Short(mapid)
        item['Count'] = nbt.TAG_Byte(1)
        item['tag'] = nbt.TAG_Compound()
        item['tag']['display'] = nbt.TAG_Compound()
        name = dungeon.dungeon_name + ' Lv {l}'
        item['tag']['display']['Name'] = nbt.TAG_String(name.format(l=level))
        item['tag']['display']['MapColor'] = nbt.TAG_Int(self.mapcolor)
        print item['tag']['display']['Name'].value

        return item
Esempio n. 37
0
 def __init__(self):
     self.loc = Vec(0, 0, 0)
     self.material = None
     self.direction = 0
     self.doors = []
Esempio n. 38
0
def res_make_catwalk(_, res):
    """Speciallised result to generate catwalks from markers.

    Only runs once, and then quits the condition list.
    """
    utils.con_log("Starting catwalk generator...")
    marker = resolve_inst(res["markerInst"])
    output_target = res["output_name", "MARKER"]

    instances = {
        name: resolve_inst(res[name, ""])[0]
        for name in (
            "straight_128",
            "straight_256",
            "straight_512",
            "corner",
            "tjunction",
            "crossjunction",
            "end",
            "stair",
            "end_wall",
            "support_wall",
            "support_ceil",
            "support_floor",
            "single_wall",
            "markerInst",
        )
    }
    # If there are no attachments remove a catwalk piece
    instances["NONE"] = ""
    if instances["end_wall"] == "":
        instances["end_wall"] = instances["end"]

    connections = {}  # The directions this instance is connected by (NSEW)
    markers = {}

    for inst in VMF.by_class["func_instance"]:
        if inst["file"].casefold() not in marker:
            continue
        #                   [North, South, East,  West ]
        connections[inst] = [False, False, False, False]
        markers[inst["targetname"]] = inst

    if not markers:
        return True  # No catwalks!

    utils.con_log("Conn:", connections)
    utils.con_log("Markers:", markers)

    # First loop through all the markers, adding connecting sections
    for inst in markers.values():
        for conn in inst.outputs:
            if conn.output != output_target or conn.input != output_target:
                # Indicator toggles or similar, delete these
                print("Removing ", conn.target)
                for del_inst in VMF.by_target[conn.target]:
                    del_inst.remove()
                continue

            inst2 = markers[conn.target]
            print(inst["targetname"], "<->", inst2["targetname"])
            origin1 = Vec.from_str(inst["origin"])
            origin2 = Vec.from_str(inst2["origin"])
            if origin1.x != origin2.x and origin1.y != origin2.y:
                utils.con_log("Instances not aligned!")
                continue

            y_dir = origin1.x == origin2.x  # Which way the connection is
            if y_dir:
                dist = abs(origin1.y - origin2.y)
            else:
                dist = abs(origin1.x - origin2.x)
            vert_dist = origin1.z - origin2.z

            utils.con_log("Dist =", dist, ", Vert =", vert_dist)

            if dist // 2 < vert_dist:
                # The stairs are 2 long, 1 high.
                utils.con_log("Not enough room for stairs!")
                continue

            if dist > 128:
                # add straight sections in between
                place_catwalk_connections(instances, origin1, origin2)

            # Update the lists based on the directions that were set
            conn_lst1 = connections[inst]
            conn_lst2 = connections[inst2]
            if origin1.x < origin2.x:
                conn_lst1[2] = True  # E
                conn_lst2[3] = True  # W
            elif origin2.x < origin1.x:
                conn_lst1[3] = True  # W
                conn_lst2[2] = True  # E

            if origin1.y < origin2.y:
                conn_lst1[0] = True  # N
                conn_lst2[1] = True  # S
            elif origin2.y < origin1.y:
                conn_lst1[1] = True  # S
                conn_lst2[0] = True  # N

        inst.outputs.clear()  # Remove the outputs now, they're useless

    for inst, dir_mask in connections.items():
        # Set the marker instances based on the attached walkways.
        print(inst["targetname"], dir_mask)
        angle = Vec.from_str(inst["angles"], 0, 0, 0)
        new_type, inst["angles"] = utils.CONN_LOOKUP[tuple(dir_mask)]
        inst["file"] = instances[CATWALK_TYPES[new_type]]

        normal = Vec(0, 0, 1).rotate(angle.x, angle.y, angle.z)
        ":type normal: Vec"

        if new_type is utils.CONN_TYPES.side:
            # If the end piece is pointing at a wall, switch the instance.
            if normal.z == 0:
                # Treat booleans as ints to get the direction the connection is
                # in - True == 1, False == 0
                conn_dir = Vec(x=dir_mask[2] - dir_mask[3], y=dir_mask[0] - dir_mask[1], z=0)  # +E, -W  # +N, -S,
                if normal == conn_dir:
                    inst["file"] = instances["end_wall"]
            continue  # We never have normal supports on end pieces
        elif new_type is utils.CONN_TYPES.none:
            # Unconnected catwalks on the wall switch to a special instance.
            # This lets players stand next to a portal surface on the wall.
            if normal.z == 0:
                inst["file"] = instances["single_wall"]
                inst["angles"] = INST_ANGLE[normal.as_tuple()]
            else:
                inst.remove()
            continue  # These don't get supports otherwise

        # Add regular supports
        if normal == (0, 0, 1):
            supp = instances["support_floor"]
        elif normal == (0, 0, -1):
            supp = instances["support_ceil"]
        else:
            supp = instances["support_wall"]

        if supp:
            VMF.create_ent(
                classname="func_instance", origin=inst["origin"], angles=INST_ANGLE[normal.as_tuple()], file=supp
            )

    utils.con_log("Finished catwalk generation!")
    return True  # Don't run this again
Esempio n. 39
0
 def render(self):
     pn = perlin.SimplexNoise(256)
     # Find all the valid halls. These are halls with a size > 0.
     # We'll store a random position within the range of the hall.
     halls = [0, 0, 0, 0]
     hallcount = 0
     wires = set()
     #wirehooks = set()
     for h in xrange(4):
         if (self.parent.halls[h].size > 0):
             halls[h] = \
                 self.parent.halls[h].offset + 1 + \
                 random.randint(0, self.parent.halls[h].size - 3)
             hallcount += 1
     # We won't draw just half a bridge, unless this is a sandpit. (yet)
     if (hallcount < 2 and self.sandpit is False):
         return
     midpoint = self.parent.parent.room_size / 2
     y = self.parent.canvasHeight()
     offset = self.parent.loc
     # Look for the X bounds between halls.
     if (halls[0] != 0 and halls[2] != 0):
         x1 = halls[0]
         x2 = halls[2]
     elif (halls[0] != 0):
         x1 = halls[0]
         x2 = x1
     elif (halls[2] != 0):
         x2 = halls[2]
         x1 = x2
     else:
         x1 = midpoint
         x2 = midpoint
     # Look for the Z bounds between halls.
     if (halls[1] != 0 and halls[3] != 0):
         z1 = halls[1]
         z2 = halls[3]
     elif (halls[1] != 0):
         z1 = halls[1]
         z2 = z1
     elif (halls[3] != 0):
         z2 = halls[3]
         z1 = z2
     else:
         z1 = midpoint
         z2 = midpoint
     # Now construct our points.
     # c1-4 are the corners of the connecting
     # box. h0-3 are the start points of the halls.
     c1 = Vec(x1, y, z1)
     c2 = Vec(x2, y, z1)
     c3 = Vec(x2, y, z2)
     c4 = Vec(x1, y, z2)
     h0 = Vec(x1, y, self.parent.hallLength[0])
     h1 = Vec(self.parent.parent.room_size - self.parent.hallLength[1] - 1,
              y, z1)
     h2 = Vec(x2, y,
              self.parent.parent.room_size - self.parent.hallLength[2] - 1)
     h3 = Vec(self.parent.hallLength[3], y, z2)
     # Sandpit?
     mat = random.choice(self.slabtypes)
     if (self.sandpit is True):
         # Draw the false sand floor
         mat = materials.Sand
         c = self.parent.canvasCenter()
         y = self.parent.canvasHeight()
         r = random.randint(1, 1000)
         maxd = max(1, self.parent.canvasWidth(),
                    self.parent.canvasLength())
         for x in utils.iterate_points_inside_flat_poly(
                 *self.parent.canvas):
             p = x + self.parent.loc
             d = ((Vec2f(x.x, x.z) - c).mag()) / maxd
             n = (pn.noise3(
                 (p.x + r) / 4.0, y / 4.0, p.z / 4.0) + 1.0) / 2.0
             if (n >= d + .10):
                 self.parent.parent.setblock(p, materials.Sand)
             elif (n >= d):
                 self.parent.parent.setblock(p, materials.Gravel)
             else:
                 self.parent.parent.setblock(p, materials._floor)
         # Find wire locations
         # h0
         # Cool fact: in 12w30c tripwires will trigger sand without hooks.
         if (halls[0] != 0):
             for x in xrange(1, self.parent.halls[0].size - 1):
                 p = Vec(self.parent.halls[0].offset + x, y - 1,
                         self.parent.hallLength[0])
                 # if x == 0:
                 #    wirehooks.add((p, 4+3))
                 # elif x == self.parent.halls[0].size-1:
                 #    wirehooks.add((p, 4+1))
                 # else:
                 #    wires.add(p)
                 wires.add(p)
         # h1
         if (halls[1] != 0):
             for x in xrange(1, self.parent.halls[1].size - 1):
                 wires.add(
                     Vec((self.parent.parent.room_size -
                          self.parent.hallLength[1] - 1), y - 1,
                         self.parent.halls[1].offset + x))
         # h2
         if (halls[2] != 0):
             for x in xrange(1, self.parent.halls[2].size - 1):
                 wires.add(
                     Vec(self.parent.halls[2].offset + x, y - 1,
                         (self.parent.parent.room_size -
                          self.parent.hallLength[2] - 1)))
         # h3
         if (halls[3] != 0):
             for x in xrange(1, self.parent.halls[3].size - 1):
                 wires.add(
                     Vec(self.parent.hallLength[3], y - 1,
                         self.parent.halls[3].offset + x))
         for p in wires:
             self.parent.parent.setblock(offset + p.down(1),
                                         materials.Gravel,
                                         lock=True)
             self.parent.parent.setblock(offset + p,
                                         materials.Tripwire,
                                         hide=True)
         # for p in wirehooks:
         #    self.parent.parent.setblock(offset+p[0].down(1), mat)
         #    self.parent.parent.setblock(offset+p[0],
         #                                materials.TripwireHook, p[1])
     # Draw the bridges, if a hallway exists.
     # h0 -> c1
     # h1 -> c2
     # h2 -> c3
     # h3 -> c4
     if (halls[0] != 0):
         for p in utils.iterate_cube(offset + h0, offset + c1):
             self.parent.parent.setblock(p, mat)
     if (halls[1] != 0):
         for p in utils.iterate_cube(offset + h1, offset + c2):
             self.parent.parent.setblock(p, mat)
     if (halls[2] != 0):
         for p in utils.iterate_cube(offset + h2, offset + c3):
             self.parent.parent.setblock(p, mat)
     if (halls[3] != 0):
         for p in utils.iterate_cube(offset + h3, offset + c4):
             self.parent.parent.setblock(p, mat)
     # Draw the connecting bridges.
     # c1 -> c2
     # c2 -> c3
     # c3 -> c4
     for p in utils.iterate_cube(offset + c1, offset + c2):
         self.parent.parent.setblock(p, mat)
     for p in utils.iterate_cube(offset + c2, offset + c3):
         self.parent.parent.setblock(p, mat)
     for p in utils.iterate_cube(offset + c3, offset + c4):
         self.parent.parent.setblock(p, mat)
Esempio n. 40
0
treasure_SpawnMaxNearbyEntities = 0
treasure_SpawnMinDelay = 0
treasure_SpawnMaxDelay = 0
treasure_SpawnRequiredPlayerRange = 0
chest_traps = '3'
sand_traps = '40'
skeleton_balconies = '25'
fill_caves = 'False'
torches_position = 3
hall_piston_traps = 75
resetting_hall_pistons = 'True'
secret_rooms = '75'
silverfish = '0'
maps = '0'
mapstore = ''
portal_exit = Vec(0, 0, 0)
dungeon_name = None
river_biomes = [7, 11]
ocean_biomes = [0, 10, 24]

master_halls = []
master_hall_traps = []
master_rooms = []
master_srooms = []
master_features = []
master_stairwells = []
master_floors = []
master_ruins = [('blank', 1)]
default_entrances = []
master_entrances = {}
master_treasure = [('pitwitharchers', 1)]
Esempio n. 41
0
class BackGround:
    # === CLASS VARIABLES ===
    IMG_ID = 0
    # cloud
    CLOUD_W, CLOUD_H = 48, 16
    CLOUD_normal = Rect(0, 80, CLOUD_W, CLOUD_H, COLKEY)
    CLOUD_INIT_POS = [Vec(280, 26), Vec(400, 16), Vec(550, 30)]

    # Ground
    GND_W, GND_H = 128, 16
    GND_normal = Rect(0, 128, GND_W, GND_H)
    GND_INIT_POS = [Vec(0, 88), Vec(GND_W, 88), Vec(2 * GND_W, 88)]

    INIT_VELOCITY_X = -4

    def __init__(self):
        self.initialize()
        self.showInfo()

    def initialize(self):
        self.cloud_velocity = Vec(self.INIT_VELOCITY_X // 4, 0)
        self.gnd_velocity = Vec(self.INIT_VELOCITY_X,
                                0)  # same with enemy's velocity
        # cloud pos(list)
        self.cloud_pos = deepcopy(self.CLOUD_INIT_POS)

        # ground pos(list)
        self.gnd_pos = deepcopy(self.GND_INIT_POS)

    def showInfo(self):
        pass

    def update(self):
        if Player.getState() == "IDLE":
            return
        # update velocity, pos
        self.updateVel()
        if pyxel.frame_count % 2:
            for i in range(len(self.cloud_pos)):
                self.cloud_pos[i] = Vec(
                    self.cloud_pos[i].x + self.cloud_velocity.x,
                    self.cloud_pos[i].y)
            for i in range(len(self.gnd_pos)):
                self.gnd_pos[i] = Vec(self.gnd_pos[i].x + self.gnd_velocity.x,
                                      self.gnd_pos[i].y)

        # 左端についたら右端に戻す
        # lastに合わせて距離を保つ
        for i in range(len(self.cloud_pos)):
            if self.cloud_pos[i].x < -50:
                self.cloud_pos[i] = Vec(self.CLOUD_INIT_POS[-1].x,
                                        self.cloud_pos[i].y)
        for i in range(len(self.gnd_pos)):
            if self.gnd_pos[i].x < -120:
                self.gnd_pos[i] = Vec(self.GND_INIT_POS[-1].x,
                                      self.gnd_pos[i].y)

    def blt(self):
        for i, pos in enumerate(self.cloud_pos):
            pyxel.blt(pos.x, pos.y, BackGround.IMG_ID,
                      *BackGround.CLOUD_normal.getRect())
        for i, pos in enumerate(self.gnd_pos):
            pyxel.blt(pos.x, pos.y, BackGround.IMG_ID,
                      *BackGround.GND_normal.getRect())

    def updateVel(self):
        # TODO: adjast the coefs
        dif = (Score.getScore() // 100)
        vel_x = self.INIT_VELOCITY_X - dif
        self.velocity = Vec(vel_x, 0)
Esempio n. 42
0
def res_fizzler_pair(begin_inst, res):
    """Modify the instance of a fizzler to link with its pair.

    Each pair will be given a name along the lines of "fizz_name-model1334".
    Values:
        - StartInst, EndInst: The instances used for each end
        - MidInst: An instance placed every 128 units between emitters.
    """
    orig_target = begin_inst['targetname']

    if 'modelEnd' in orig_target:
        return  # We only execute starting from the start side.

    orig_target = orig_target[:-11]  # remove "_modelStart"
    end_name = orig_target + '_modelEnd'  # What we search for

    # The name all these instances get
    pair_name = orig_target + '-model' + str(begin_inst.id)

    orig_file = begin_inst['file']

    begin_file = res['StartInst', orig_file]
    end_file = res['EndInst', orig_file]
    mid_file = res['MidInst', '']

    begin_inst['file'] = begin_file
    begin_inst['targetname'] = pair_name

    direction = Vec(0, 0, 1).rotate_by_str(begin_inst['angles'])

    begin_pos = Vec.from_str(begin_inst['origin'])
    axis_1, axis_2, main_axis = PAIR_AXES[direction.as_tuple()]
    for end_inst in vbsp.VMF.by_class['func_instance']:
        if end_inst['targetname', ''] != end_name:
            # Only examine this barrier hazard's instances!
            continue
        end_pos = Vec.from_str(end_inst['origin'])
        if (
                begin_pos[axis_1] == end_pos[axis_1] and
                begin_pos[axis_2] == end_pos[axis_2]
                ):
            length = int(end_pos[main_axis] - begin_pos[main_axis])
            break
    else:
        LOGGER.warning('No matching pair for {}!!', orig_target)
        return
    end_inst['targetname'] = pair_name
    end_inst['file'] = end_file

    if mid_file != '':
        # Go 64 from each side, and always have at least 1 section
        # A 128 gap will have length = 0
        for dis in range(0, abs(length) + 1, 128):
            new_pos = begin_pos + direction*dis
            vbsp.VMF.create_ent(
                classname='func_instance',
                targetname=pair_name,
                angles=begin_inst['angles'],
                file=mid_file,
                origin=new_pos.join(' '),
            )
Esempio n. 43
0
import inspect
import random
import sys

import cfg
import materials
from utils import (
    Vec,
    enum,
    iterate_cube,
    get_tile_entity_tags,
    weighted_choice
)

dv = [
    Vec(0, -1, 0),
    Vec(1, 0, 0),
    Vec(0, 1, 0),
    Vec(-1, 0, 0)
]
dirs = enum('N', 'E', 'S', 'W')


class Blank(object):
    _name = 'blank'
    _min_width = 0
    _max_width = 32
    _min_length = 0
    _max_length = 32

    def __init__(self, parent, position, size, length, direction):
Esempio n. 44
0
def res_track_plat(_, res):
    """Logic specific to Track Platforms.

    This allows switching the instances used depending on if the track
    is horizontal or vertical and sets the track
    targetnames to a useful value.
    """
    # Get the instances from editoritems
    (inst_bot_grate, inst_bottom, inst_middle, inst_top, inst_plat, inst_plat_oscil, inst_single) = resolve_inst(
        res["orig_item"]
    )
    single_plat_inst = res["single_plat", ""]
    track_targets = res["track_name", ""]

    track_files = [inst_bottom, inst_middle, inst_top, inst_single]
    platforms = [inst_plat, inst_plat_oscil]

    # All the track_set in the map, indexed by origin
    track_instances = {
        Vec.from_str(inst["origin"]).as_tuple(): inst
        for inst in VMF.by_class["func_instance"]
        if inst["file"].casefold() in track_files
    }
    utils.con_log("Track instances:")
    utils.con_log("\n".join("{!s}: {}".format(k, v["file"]) for k, v in track_instances.items()))

    # Now we loop through all platforms in the map, and then locate their
    # track_set
    for plat_inst in VMF.by_class["func_instance"]:
        if plat_inst["file"].casefold() not in platforms:
            continue  # Not a platform!

        utils.con_log('Modifying "' + plat_inst["targetname"] + '"!')

        plat_loc = Vec.from_str(plat_inst["origin"])
        angles = Vec.from_str(plat_inst["angles"])
        # The direction away from the wall/floor/ceil
        normal = Vec(0, 0, 1).rotate(angles.x, angles.y, angles.z)

        for tr_origin, first_track in track_instances.items():
            if plat_loc == tr_origin:
                # Check direction

                if normal == Vec(0, 0, 1).rotate(*Vec.from_str(first_track["angles"])):
                    break
        else:
            raise Exception('Platform "{}" has no track!'.format(plat_inst["targetname"]))

        track_type = first_track["file"].casefold()
        if track_type == inst_single:
            # Track is one block long, use a single-only instance and
            # remove track!
            plat_inst["file"] = single_plat_inst
            first_track.remove()
            continue  # Next platform

        track_set = set()
        if track_type == inst_top or track_type == inst_middle:
            # search left
            track_scan(track_set, track_instances, first_track, middle_file=inst_middle, x_dir=-1)
        if track_type == inst_bottom or track_type == inst_middle:
            # search right
            track_scan(track_set, track_instances, first_track, middle_file=inst_middle, x_dir=+1)

        # Give every track a targetname matching the platform
        for ind, track in enumerate(track_set, start=1):
            if track_targets == "":
                track["targetname"] = plat_inst["targetname"]
            else:
                track["targetname"] = plat_inst["targetname"] + "-" + track_targets + str(ind)

        # Now figure out which way the track faces:

        # The direction horizontal track is offset
        side_dir = Vec(0, 1, 0).rotate(*Vec.from_str(first_track["angles"]))

        # The direction of the platform surface
        facing = Vec(-1, 0, 0).rotate(angles.x, angles.y, angles.z)
        if side_dir == facing:
            track_facing = "HORIZ"
        elif side_dir == -facing:
            track_facing = "HORIZ_MIRR"
        else:
            track_facing = "VERT"
        # Now add the suffixes
        if track_facing == "VERT":
            if utils.conv_bool(res["vert_suffix", ""]):
                for inst in track_set:
                    add_suffix(inst, "_vert")
                if utils.conv_bool(res["plat_suffix", ""]):
                    add_suffix(plat_inst, "_vert")
        elif track_facing == "HORIZ_MIRR":
            if utils.conv_bool(res["horiz_suffix", ""]):
                for inst in track_set:
                    add_suffix(inst, "_horiz_mirrored")
                if utils.conv_bool(res["plat_suffix", ""]):
                    add_suffix(plat_inst, "_horiz")
        else:  # == 'HORIZ'
            if utils.conv_bool(res["horiz_suffix", ""]):
                for inst in track_set:
                    add_suffix(inst, "_horiz")
                if utils.conv_bool(res["plat_suffix", ""]):
                    add_suffix(plat_inst, "_horiz")
    return True  # Only run once!
Esempio n. 45
0
def res_faith_mods(inst: VLib.Entity, res: Property):
    """Modify the trigger_catrapult that is created for ItemFaithPlate items.

    Values:
        - raise_trig: Raise or lower the trigger_catapults by this amount.
        - angled_targ, angled_in: Instance entity and input for angled plates
        - straight_targ, straight_in: Instance entity and input for
            straight plates
        - instvar: A $replace value to set to either 'angled' or '
            'straight'.
        - enabledVar: A $replace value which will be copied to the main
            trigger's Start Disabled value (and inverted).
        - trig_temp: An ID for a template brush to add. This will be offset by
            the trigger's position (in the case of the 'helper' trigger).
    """
    # Get data about the trigger this instance uses for flinging
    fixup_var = res['instvar', '']
    trig_enabled = res['enabledVar', None]
    trig_temp = res['trig_temp', '']
    offset = utils.conv_int(res['raise_trig', '0'])
    if offset:
        offset = Vec(0, 0, offset).rotate_by_str(inst['angles', '0 0 0'])
    else:
        offset = Vec()

    if trig_enabled is not None:
        trig_enabled = utils.conv_bool(inst.fixup[trig_enabled])
    else:
        trig_enabled = None

    for trig in vbsp.VMF.by_class['trigger_catapult']:
        if inst['targetname'] not in trig['targetname']:
            continue

        # Edit both the normal and the helper trigger..
        trig_origin = trig['origin'] = Vec.from_str(trig['origin']) + offset

        if offset and not trig_temp:
            # No template, shift the current brushes.
            for solid in trig.solids:
                solid.translate(offset)
        elif trig_temp:
            trig.solids = conditions.import_template(
                temp_name=trig_temp,
                origin=trig_origin,
                angles=Vec.from_str(inst['angles']),
                force_type=conditions.TEMP_TYPES.world,
            ).world
            # Remove the trigger solids from worldspawn..
            for solid in trig.solids:
                vbsp.VMF.remove_brush(solid)

        if trig_enabled is not None and 'helper' not in trig['targetname']:
            trig['startdisabled'] = utils.bool_as_int(not trig_enabled)

        # Inspect the outputs to determine the type.
        # We also change them if desired, since that's not possible
        # otherwise.

        for out in trig.outputs:
            if out.inst_in == 'animate_angled_relay':
                # Instead of an instance: output, use local names.
                # This allows us to strip the proxy, as well as use
                # overlay instances.
                out.inst_in = None
                out.target = conditions.local_name(
                    inst,
                    res['angled_targ', 'animate_angled_relay']
                )
                out.input = res['angled_in', 'Trigger']
                if fixup_var:
                    inst.fixup[fixup_var] = 'angled'
                break  # There's only one output we want to look for...

            elif out.inst_in == 'animate_straightup_relay':
                out.inst_in = None
                out.target = conditions.local_name(
                    inst,
                    res[
                        'straight_targ',
                        'animate_straightup_relay'
                    ],
                )
                out.input = res['straight_in', 'Trigger']

                if fixup_var:
                    inst.fixup[fixup_var] = 'straight'
                break
Esempio n. 46
0
def res_track_plat(_, res):
    """Logic specific to Track Platforms.

    This allows switching the instances used depending on if the track
    is horizontal or vertical and sets the track
    targetnames to a useful value.
    Values:
        - Orig_item: The "<ITEM_ID>" for the track platform, with angle brackets
        - Single_plat: An instance used for platform with 1 rail
        - Track_name: The name to give to the tracks.
        - Vert_suffix: Add suffixes to vertical tracks
            (_vert)
        - Horiz_suffix: Add suffixes to horizontal tracks
            (_horiz, _horiz_mirrored)
        - plat_suffix: Also add the above _vert or _horiz suffixes to
            the platform.
        - plat_var: If set, save the orientation to the given $fixup variable
    """
    # Get the instances from editoritems
    (
        inst_bot_grate, inst_bottom, inst_middle,
        inst_top, inst_plat, inst_plat_oscil, inst_single
    ) = resolve_inst(res['orig_item'])
    single_plat_inst = res['single_plat', '']
    track_targets = res['track_name', '']

    track_files = [inst_bottom, inst_middle, inst_top, inst_single]
    platforms = [inst_plat, inst_plat_oscil]

    # All the track_set in the map, indexed by origin
    track_instances = {
        Vec.from_str(inst['origin']).as_tuple(): inst
        for inst in
        vbsp.VMF.by_class['func_instance']
        if inst['file'].casefold() in track_files
    }

    LOGGER.debug('Track instances:')
    LOGGER.debug('\n'.join(
        '{!s}: {}'.format(k, v['file'])
        for k, v in
        track_instances.items()
    ))

    if not track_instances:
        return RES_EXHAUSTED

    # Now we loop through all platforms in the map, and then locate their
    # track_set
    for plat_inst in vbsp.VMF.by_class['func_instance']:
        if plat_inst['file'].casefold() not in platforms:
            continue  # Not a platform!

        LOGGER.debug('Modifying "' + plat_inst['targetname'] + '"!')

        plat_loc = Vec.from_str(plat_inst['origin'])
        # The direction away from the wall/floor/ceil
        normal = Vec(0, 0, 1).rotate_by_str(
            plat_inst['angles']
        )

        for tr_origin, first_track in track_instances.items():
            if plat_loc == tr_origin:
                # Check direction

                if normal == Vec(0, 0, 1).rotate(
                        *Vec.from_str(first_track['angles'])
                        ):
                    break
        else:
            raise Exception('Platform "{}" has no track!'.format(
                plat_inst['targetname']
            ))

        track_type = first_track['file'].casefold()
        if track_type == inst_single:
            # Track is one block long, use a single-only instance and
            # remove track!
            plat_inst['file'] = single_plat_inst
            first_track.remove()
            continue  # Next platform

        track_set = set()
        if track_type == inst_top or track_type == inst_middle:
            # search left
            track_scan(
                track_set,
                track_instances,
                first_track,
                middle_file=inst_middle,
                x_dir=-1,
            )
        if track_type == inst_bottom or track_type == inst_middle:
            # search right
            track_scan(
                track_set,
                track_instances,
                first_track,
                middle_file=inst_middle,
                x_dir=+1,
            )

        # Give every track a targetname matching the platform
        for ind, track in enumerate(track_set, start=1):
            if track_targets == '':
                track['targetname'] = plat_inst['targetname']
            else:
                track['targetname'] = (
                    plat_inst['targetname'] +
                    '-' +
                    track_targets + str(ind)
                )

        # Now figure out which way the track faces:

        # The direction horizontal track is offset
        side_dir = Vec(0, 1, 0).rotate_by_str(first_track['angles'])

        # The direction of the platform surface
        facing = Vec(-1, 0, 0).rotate_by_str(plat_inst['angles'])
        if side_dir == facing:
            track_facing = 'HORIZ'
        elif side_dir == -facing:
            track_facing = 'HORIZ_MIRR'
        else:
            track_facing = 'VERT'
        # Now add the suffixes
        if track_facing == 'VERT':
            if utils.conv_bool(res['vert_suffix', '']):
                for inst in track_set:
                    conditions.add_suffix(inst, '_vert')
                if utils.conv_bool(res['plat_suffix', '']):
                    conditions.add_suffix(plat_inst, '_vert')
        elif track_facing == 'HORIZ_MIRR':
            if utils.conv_bool(res['horiz_suffix', '']):
                for inst in track_set:
                    conditions.add_suffix(inst, '_horiz_mirrored')
                if utils.conv_bool(res['plat_suffix', '']):
                    conditions.add_suffix(plat_inst, '_horiz')
        else:  # == 'HORIZ'
            if utils.conv_bool(res['horiz_suffix', '']):
                for inst in track_set:
                    conditions.add_suffix(inst, '_horiz')
                if utils.conv_bool(res['plat_suffix', '']):
                    conditions.add_suffix(plat_inst, '_horiz')

        plat_var = res['plat_var', '']
        if plat_var != '':
            # Skip the '_mirrored' section if needed
            plat_inst.fixup[plat_var] = track_facing[:5].lower()

    return RES_EXHAUSTED # Don't re-run
Esempio n. 47
0
import inspect
import random
import sys

import cfg
import materials
from utils import (Vec, enum, iterate_cube, get_tile_entity_tags,
                   weighted_choice)

dv = [Vec(0, -1, 0), Vec(1, 0, 0), Vec(0, 1, 0), Vec(-1, 0, 0)]
dirs = enum('N', 'E', 'S', 'W')


class Blank(object):
    _name = 'blank'
    _min_width = 0
    _max_width = 32
    _min_length = 0
    _max_length = 32

    def __init__(self, parent, position, size, length, direction):
        self.parent = parent
        self.position = position
        self.size = size
        self.length = length
        self.direction = direction
        # Set delta width and length vectors based on halleasy direction.
        if direction == dirs.E:
            self.dl = Vec(1, 0, 0)
            self.dw = Vec(0, 0, 1)
        else: