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 )
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(' ')
def res_add_overlay_inst(inst, res): """Add another instance on top of this one. Values: File: The filename. Fixup Style: The Fixup style for the instance. '0' (default) is Prefix, '1' is Suffix, and '2' is None. Copy_Fixup: If true, all the $replace values from the original instance will be copied over. move_outputs: If true, outputs will be moved to this instance. offset: The offset (relative to the base) that the instance will be placed. Can be set to '<piston_top>' and '<piston_bottom>' to offset based on the configuration of piston platform handles. angles: If set, overrides the base instance angles. This does not affect the offset property. fixup: Keyvalues in this block will be copied to the overlay entity. If the value starts with $, the variable will be copied over. If this is present, copy_fixup will be disabled """ angle = res["angles", inst["angles", "0 0 0"]] overlay_inst = vbsp.VMF.create_ent( classname="func_instance", targetname=inst["targetname", ""], file=resolve_inst(res["file", ""])[0], angles=angle, origin=inst["origin"], fixup_style=res["fixup_style", "0"], ) # Don't run if the fixup block exists.. if utils.conv_bool(res["copy_fixup", "1"]) and "fixup" not in res: # Copy the fixup values across from the original instance for fixup, value in inst.fixup.items(): overlay_inst.fixup[fixup] = value # Copy additional fixup values over for prop in res.find_key("Fixup", []): # type: Property if prop.value.startswith("$"): overlay_inst.fixup[prop.real_name] = inst.fixup[prop.value] else: overlay_inst.fixup[prop.real_name] = prop.value if utils.conv_bool(res["move_outputs", "0"]): overlay_inst.outputs = inst.outputs inst.outputs = [] if "offset" in res: folded_off = res["offset"].casefold() # Offset the overlay by the given distance # Some special placeholder values: if folded_off == "<piston_bottom>": offset = Vec(z=utils.conv_int(inst.fixup["$bottom_level"]) * 128) elif folded_off == "<piston_top>": offset = Vec(z=utils.conv_int(inst.fixup["$top_level"], 1) * 128) else: # Regular vector offset = Vec.from_str(res["offset"]) offset.rotate_by_str(inst["angles", "0 0 0"]) overlay_inst["origin"] = (offset + Vec.from_str(inst["origin"])).join(" ") return overlay_inst