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
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()
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']
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
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(' '), )
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, )
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 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(" "), )
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.
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)
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
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
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
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)]
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_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, )
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]) )
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
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)
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'], )
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())
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 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 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
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
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, )
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)
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']
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
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)
def updateVel(self): # TODO: adjast the coefs dif = (Score.getScore() // 100) vel_x = self.INIT_VELOCITY_X - dif self.velocity = Vec(vel_x, 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, })
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)
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)
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()
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
def __init__(self): self.loc = Vec(0, 0, 0) self.material = None self.direction = 0 self.doors = []
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
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)
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)]
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)
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(' '), )
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):
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!
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
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
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: