本文整理汇总了Python中srctools.Property.find_key方法的典型用法代码示例。如果您正苦于以下问题:Python Property.find_key方法的具体用法?Python Property.find_key怎么用?Python Property.find_key使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类srctools.Property
的用法示例。
在下文中一共展示了Property.find_key方法的13个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。
示例1: load_conf
# 需要导入模块: from srctools import Property [as 别名]
# 或者: from srctools.Property import find_key [as 别名]
def load_conf(prop_block: Property):
"""Read the config and build our dictionaries."""
global INST_SPECIAL
# Extra definitions: key -> filename.
# Make sure to do this first, so numbered instances are set in
# ITEM_FOR_FILE.
for prop in prop_block.find_key('CustInstances', []):
CUST_INST_FILES[prop.name] = special_inst = {}
for inst in prop:
file = inst.value.casefold()
special_inst[inst.name] = file
ITEM_FOR_FILE[file] = (prop.name, inst.name)
# Normal instances: index -> filename
for prop in prop_block.find_key('Allinstances', []):
INSTANCE_FILES[prop.name] = inst_list = []
for ind, inst in enumerate(prop):
file = inst.value.casefold()
inst_list.append(file)
ITEM_FOR_FILE[file] = (prop.name, ind)
INST_SPECIAL = {
key.casefold(): resolve(val_string, silent=True)
for key, val_string in
SPECIAL_INST.items()
}
示例2: set_ent_keys
# 需要导入模块: from srctools import Property [as 别名]
# 或者: from srctools.Property import find_key [as 别名]
def set_ent_keys(
ent: Entity,
inst: Entity,
prop_block: Property,
block_name: str='Keys',
) -> None:
"""Copy the given key prop block to an entity.
This uses the keys and 'localkeys' properties on the prop_block.
Values with $fixup variables will be treated appropriately.
LocalKeys keys will be changed to use instance-local names, where needed.
block_name lets you change the 'keys' suffix on the prop_block name.
ent can be any mapping.
"""
for prop in prop_block.find_key(block_name, []):
ent[prop.real_name] = resolve_value(inst, prop.value)
for prop in prop_block.find_key('Local' + block_name, []):
if prop.value.startswith('$'):
val = inst.fixup[prop.value]
else:
val = prop.value
if val.startswith('@'):
ent[prop.real_name] = val
else:
ent[prop.real_name] = local_name(inst, val)
示例3: res_cust_antline_setup
# 需要导入模块: from srctools import Property [as 别名]
# 或者: from srctools.Property import find_key [as 别名]
def res_cust_antline_setup(res: Property):
if 'wall' in res:
wall_type = antlines.AntType.parse(res.find_key('wall'))
else:
wall_type = None
if 'floor' in res:
floor_type = antlines.AntType.parse(res.find_key('floor'))
else:
floor_type = wall_type
return (
wall_type,
floor_type,
res.bool('remove_signs'),
res['toggle_var', ''],
)
示例4: save_load_itemvar
# 需要导入模块: from srctools import Property [as 别名]
# 或者: from srctools.Property import find_key [as 别名]
def save_load_itemvar(prop: Property=None) -> Optional[Property]:
"""Save or load item variables into the palette."""
if prop is None:
prop = Property('', [])
for group in CONFIG_ORDER:
conf = Property(group.id, [])
for widget in group.widgets: # ItemVariant special case.
if widget.values is not None:
conf.append(Property(widget.id, widget.values.get()))
for widget in group.multi_widgets:
conf.append(Property(widget.id, [
Property(str(tim_val), var.get())
for tim_val, var in
widget.values
]))
prop.append(conf)
return prop
else:
# Loading.
for group in CONFIG_ORDER:
conf = prop.find_key(group.id, [])
for widget in group.widgets:
if widget.values is not None: # ItemVariants
try:
widget.values.set(conf[widget.id])
except LookupError:
pass
for widget in group.multi_widgets:
time_conf = conf.find_key(widget.id, [])
for tim_val, var in widget.values:
try:
var.set(time_conf[str(tim_val)])
except LookupError:
pass
return None
示例5: from_file
# 需要导入模块: from srctools import Property [as 别名]
# 或者: from srctools.Property import find_key [as 别名]
def from_file(cls, path, zip_file):
"""Initialise from a file.
path is the file path for the map inside the zip, without extension.
zip_file is either a ZipFile or FakeZip object.
"""
# Some P2Cs may have non-ASCII characters in descriptions, so we
# need to read it as bytes and convert to utf-8 ourselves - zips
# don't convert encodings automatically for us.
try:
with zip_open_bin(zip_file, path + '.p2c') as file:
props = Property.parse(
# Decode the P2C as UTF-8, and skip unknown characters.
# We're only using it for display purposes, so that should
# be sufficent.
TextIOWrapper(
file,
encoding='utf-8',
errors='replace',
),
path,
)
except KeyValError:
# Silently fail if we can't parse the file. That way it's still
# possible to backup.
LOGGER.warning('Failed parsing puzzle file!', path, exc_info=True)
props = Property('portal2_puzzle', [])
title = None
desc = _('Failed to parse this puzzle file. It can still be backed up.')
else:
props = props.find_key('portal2_puzzle', [])
title = props['title', None]
desc = props['description', _('No description found.')]
if title is None:
title = '<' + path.rsplit('/', 1)[-1] + '.p2c>'
return cls(
filename=os.path.basename(path),
zip_file=zip_file,
title=title,
desc=desc,
is_coop=srctools.conv_bool(props['coop', '0']),
create_time=Date(props['timestamp_created', '']),
mod_time=Date(props['timestamp_modified', '']),
)
示例6: res_import_template_setup
# 需要导入模块: from srctools import Property [as 别名]
# 或者: from srctools.Property import find_key [as 别名]
def res_import_template_setup(res: Property):
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,
)
示例7: res_make_tag_fizzler_setup
# 需要导入模块: from srctools import Property [as 别名]
# 或者: from srctools.Property import find_key [as 别名]
def res_make_tag_fizzler_setup(res: Property):
"""We need this to pre-parse the fizzler type."""
if 'ioconf' in res:
fizz_type = ItemType.parse('<TAG_FIZZER>', res.find_key('ioconf'))
else:
fizz_type = None
# The distance from origin the double signs are seperated by.
sign_offset = res.int('signoffset', 16)
return (
sign_offset,
fizz_type,
res['frame_double'],
res['frame_single'],
res['blue_sign', ''],
res['blue_off_sign', ''],
res['oran_sign', ''],
res['oran_off_sign', ''],
)
示例8: res_resizeable_trigger
# 需要导入模块: from srctools import Property [as 别名]
# 或者: from srctools.Property import find_key [as 别名]
def res_resizeable_trigger(vmf: VMF, res: Property):
"""Replace two markers with a trigger brush.
This is run once to affect all of an item.
Options:
* `markerInst`: <ITEM_ID:1,2> value referencing the marker instances, or a filename.
* `markerItem`: The item's ID
* `previewConf`: A item config which enables/disables the preview overlay.
* `previewInst`: An instance to place at the marker location in preview mode.
This should contain checkmarks to display the value when testing.
* `previewMat`: If set, the material to use for an overlay func_brush.
The brush will be parented to the trigger, so it vanishes once killed.
It is also non-solid.
* `previewScale`: The scale for the func_brush materials.
* `previewActivate`, `previewDeactivate`: The VMF output to turn the
previewInst on and off.
* `triggerActivate, triggerDeactivate`: The `instance:name;Output`
outputs used when the trigger turns on or off.
* `coopVar`: The instance variable which enables detecting both Coop players.
The trigger will be a trigger_playerteam.
* `coopActivate, coopDeactivate`: The `instance:name;Output` outputs used
when coopVar is enabled. These should be suitable for a logic_coop_manager.
* `coopOnce`: If true, kill the manager after it first activates.
* `keys`: A block of keyvalues for the trigger brush. Origin and targetname
will be set automatically.
* `localkeys`: The same as above, except values will be changed to use
instance-local names.
"""
marker = instanceLocs.resolve(res['markerInst'])
marker_names = set()
for inst in vmf.by_class['func_instance']:
if inst['file'].casefold() in marker:
marker_names.add(inst['targetname'])
# Unconditionally delete from the map, so it doesn't
# appear even if placed wrongly.
inst.remove()
if not marker_names: # No markers in the map - abort
return RES_EXHAUSTED
item_id = res['markerItem']
# Synthesise the item type used for the final trigger.
item_type_sp = connections.ItemType(
id=item_id + ':TRIGGER',
output_act=Output.parse_name(res['triggerActivate', 'OnStartTouchAll']),
output_deact=Output.parse_name(res['triggerDeactivate', 'OnEndTouchAll']),
)
# For Coop, we add a logic_coop_manager in the mix so both players can
# be handled.
try:
coop_var = res['coopVar']
except LookupError:
coop_var = item_type_coop = None
coop_only_once = False
else:
coop_only_once = res.bool('coopOnce')
item_type_coop = connections.ItemType(
id=item_id + ':TRIGGER_COOP',
output_act=Output.parse_name(
res['coopActivate', 'OnChangeToAllTrue']
),
output_deact=Output.parse_name(
res['coopDeactivate', 'OnChangeToAnyFalse']
),
)
# Display preview overlays if it's preview mode, and the config is true
pre_act = pre_deact = None
if vbsp.IS_PREVIEW and vbsp_options.get_itemconf(res['previewConf', ''], False):
preview_mat = res['previewMat', '']
preview_inst_file = res['previewInst', '']
preview_scale = res.float('previewScale', 0.25)
# None if not found.
with suppress(LookupError):
pre_act = Output.parse(res.find_key('previewActivate'))
with suppress(LookupError):
pre_deact = Output.parse(res.find_key('previewDeactivate'))
else:
# Deactivate the preview_ options when publishing.
preview_mat = preview_inst_file = ''
preview_scale = 0.25
# Now go through each brush.
# We do while + pop to allow removing both names each loop through.
todo_names = set(marker_names)
while todo_names:
targ = todo_names.pop()
mark1 = connections.ITEMS.pop(targ)
for conn in mark1.outputs:
if conn.to_item.name in marker_names:
mark2 = conn.to_item
#.........这里部分代码省略.........
示例9: res_cutout_tile
# 需要导入模块: from srctools import Property [as 别名]
# 或者: from srctools.Property import find_key [as 别名]
def res_cutout_tile(vmf: srctools.VMF, res: Property):
"""Generate random quarter tiles, like in Destroyed or Retro maps.
- "MarkerItem" is the instance to look for.
- "TileSize" can be "2x2" or "4x4".
- rotateMax is the amount of degrees to rotate squarebeam models.
Materials:
- "squarebeams" is the squarebeams variant to use.
- "ceilingwalls" are the sides of the ceiling section.
- "floorbase" is the texture under floor sections.
- "tile_glue" is used on top of a thinner tile segment.
- "clip" is the player_clip texture used over floor segments.
(This allows customising the surfaceprop.)
- "Floor4x4Black", "Ceil2x2White" and other combinations can be used to
override the textures used.
"""
marker_filenames = instanceLocs.resolve(res['markeritem'])
INST_LOCS = {} # Map targetnames -> surface loc
CEIL_IO = [] # Pairs of ceil inst corners to cut out.
FLOOR_IO = [] # Pairs of floor inst corners to cut out.
overlay_ids = {} # When we replace brushes, we need to fix any overlays
# on that surface.
MATS.clear()
floor_edges = [] # Values to pass to add_floor_sides() at the end
sign_locs = set()
# If any signage is present in the map, we need to force tiles to
# appear at that location!
for over in vmf.by_class['info_overlay']:
if (
over['material'].casefold() in FORCE_TILE_MATS and
# Only check floor/ceiling overlays
over['basisnormal'] in ('0 0 1', '0 0 -1')
):
add_signage_loc(sign_locs, Vec.from_str(over['origin']))
for item in connections.ITEMS.values():
for ind_pan in item.ind_panels:
loc = Vec(0, 0, -64)
loc.localise(
Vec.from_str(ind_pan['origin']),
Vec.from_str(ind_pan['angles']),
)
add_signage_loc(sign_locs, loc)
SETTINGS = {
'floor_chance': srctools.conv_int(
res['floorChance', '100'], 100),
'ceil_chance': srctools.conv_int(
res['ceilingChance', '100'], 100),
'floor_glue_chance': srctools.conv_int(
res['floorGlueChance', '0']),
'ceil_glue_chance': srctools.conv_int(
res['ceilingGlueChance', '0']),
'rotate_beams': int(srctools.conv_float(
res['rotateMax', '0']) * BEAM_ROT_PRECISION),
'beam_skin': res['squarebeamsSkin', '0'],
'base_is_disp': srctools.conv_bool(res['dispBase', '0']),
'quad_floor': res['FloorSize', '4x4'].casefold() == '2x2',
'quad_ceil': res['CeilingSize', '4x4'].casefold() == '2x2',
}
random.seed(vbsp.MAP_RAND_SEED + '_CUTOUT_TILE_NOISE')
noise = SimplexNoise(period=4 * 40) # 4 tiles/block, 50 blocks max
# We want to know the number of neighbouring tile cutouts before
# placing tiles - blocks away from the sides generate fewer tiles.
floor_neighbours = defaultdict(dict) # all_floors[z][x,y] = count
for mat_prop in res.find_key('Materials', []):
MATS[mat_prop.name].append(mat_prop.value)
if SETTINGS['base_is_disp']:
# We want the normal brushes to become nodraw.
MATS['floorbase_disp'] = MATS['floorbase']
MATS['floorbase'] = ['tools/toolsnodraw']
# Since this uses random data for initialisation, the alpha and
# regular will use slightly different patterns.
alpha_noise = SimplexNoise(period=4 * 50)
else:
alpha_noise = None
for key, default in TEX_DEFAULT:
if key not in MATS:
MATS[key] = [default]
# Find our marker ents
for inst in vmf.by_class['func_instance']:
if inst['file'].casefold() not in marker_filenames:
continue
targ = inst['targetname']
#.........这里部分代码省略.........
示例10: res_import_template_setup
# 需要导入模块: from srctools import Property [as 别名]
# 或者: from srctools.Property import find_key [as 别名]
def res_import_template_setup(res: Property):
temp_id = res['id']
force = res['force', ''].casefold().split()
if 'white' in force:
force_colour = template_brush.MAT_TYPES.white
elif 'black' in force:
force_colour = template_brush.MAT_TYPES.black
elif 'invert' in force:
force_colour = 'INVERT'
else:
force_colour = None
if 'world' in force:
force_type = template_brush.TEMP_TYPES.world
elif 'detail' in force:
force_type = template_brush.TEMP_TYPES.detail
else:
force_type = template_brush.TEMP_TYPES.default
for size in ('2x2', '4x4', 'wall', 'special'):
if size in force:
force_grid = size
break
else:
force_grid = None
invert_var = res['invertVar', '']
color_var = res['colorVar', '']
replace_tex = defaultdict(list)
for prop in res.find_key('replace', []):
replace_tex[prop.name].append(prop.value)
rem_replace_brush = True
additional_ids = set()
transfer_overlays = '1'
try:
replace_brush = res.find_key('replaceBrush')
except NoKeyError:
replace_brush_pos = None
else:
if replace_brush.has_children():
replace_brush_pos = replace_brush['Pos', '0 0 0']
additional_ids = set(map(
srctools.conv_int,
replace_brush['additionalIDs', ''].split(),
))
rem_replace_brush = replace_brush.bool('removeBrush', True)
transfer_overlays = replace_brush['transferOverlay', '1']
else:
replace_brush_pos = replace_brush.value # type: str
replace_brush_pos = Vec.from_str(replace_brush_pos)
replace_brush_pos.z -= 64 # 0 0 0 defaults to the floor.
key_values = res.find_key("Keys", [])
if key_values:
keys = Property("", [
key_values,
res.find_key("LocalKeys", []),
])
# Ensure we have a 'origin' keyvalue - we automatically offset that.
if 'origin' not in key_values:
key_values['origin'] = '0 0 0'
# Spawn everything as detail, so they get put into a brush
# entity.
force_type = template_brush.TEMP_TYPES.detail
outputs = [
Output.parse(prop)
for prop in
res.find_children('Outputs')
]
else:
keys = None
outputs = []
visgroup_mode = res['visgroup', 'none'].casefold()
if visgroup_mode not in ('none', 'choose'):
visgroup_mode = srctools.conv_float(visgroup_mode.rstrip('%'), 0.00)
if visgroup_mode == 0:
visgroup_mode = 'none'
# Generate the function which picks which visgroups to add to the map.
if visgroup_mode == 'none':
def visgroup_func(_):
"""none = don't add any visgroups."""
return ()
elif visgroup_mode == 'choose':
def visgroup_func(groups):
"""choose = add one random group."""
return [random.choice(groups)]
else:
def visgroup_func(groups):
"""Number = percent chance for each to be added"""
for group in groups:
val = random.uniform(0, 100)
if val <= visgroup_mode:
yield group
#.........这里部分代码省略.........
示例11: generate_music_script
# 需要导入模块: from srctools import Property [as 别名]
# 或者: from srctools.Property import find_key [as 别名]
def generate_music_script(data: Property, pack_list: PackList) -> bytes:
"""Generate a soundscript file for music."""
# We also pack the filenames used for the tracks - that way funnel etc
# only get packed when needed. Stock sounds are in VPKS or in aperturetag/,
# we don't check there.
# The voice attrs used in the map - we can skip tracks
voice_attr = CONF['VoiceAttr', ''].casefold().split(';')
funnel = data.find_key('tbeam', '')
bounce = data.find_key('bouncegel', '')
speed = data.find_key('speedgel', '')
sync_funnel = data.bool('sync_funnel')
if 'base' not in data:
base = Property('base', 'bee2/silent_lp.wav')
# Don't sync to a 2-second sound.
sync_funnel = False
else:
base = data.find_key('base')
# The sounds must be present, and the items should be in the map.
has_funnel = funnel.value and (
'funnel' in voice_attr or
'excursionfunnel' in voice_attr
)
has_bounce = bounce.value and (
'bouncegel' in voice_attr or
'bluegel' in voice_attr
)
# Speed-gel sounds also play when flinging, so keep it always.
file = StringIO()
# Write the base music track
file.write(MUSIC_START.format(name='', vol='1'))
write_sound(file, base, pack_list, snd_prefix='#*')
file.write(MUSIC_BASE)
# The 'soundoperators' section is still open now.
# Add the operators to play the auxilluary sounds..
if has_funnel:
file.write(MUSIC_FUNNEL_MAIN)
if has_bounce:
file.write(MUSIC_GEL_BOUNCE_MAIN)
if speed.value:
file.write(MUSIC_GEL_SPEED_MAIN)
# End the main sound block
file.write(MUSIC_END)
if has_funnel:
# Write the 'music.BEE2_funnel' sound entry
file.write('\n')
file.write(MUSIC_START.format(name='_funnel', vol='1'))
write_sound(file, funnel, pack_list, snd_prefix='*')
# Some tracks want the funnel music to sync with the normal
# track, others randomly choose a start.
file.write(
MUSIC_FUNNEL_SYNC_STACK
if sync_funnel else
MUSIC_FUNNEL_RAND_STACK
)
file.write(MUSIC_FUNNEL_UPDATE_STACK)
if has_bounce:
file.write('\n')
file.write(MUSIC_START.format(name='_gel_bounce', vol='0.5'))
write_sound(file, bounce, pack_list, snd_prefix='*')
# Fade in fast (we never get false positives, but fade out slow
# since this disables when falling back..
file.write(MUSIC_GEL_STACK.format(fadein=0.25, fadeout=1.5))
if speed.value:
file.write('\n')
file.write(MUSIC_START.format(name='_gel_speed', vol='0.5'))
write_sound(file, speed, pack_list, snd_prefix='*')
# We need to shut off the sound fast, so portals don't confuse it.
# Fade in slow so it doesn't make much sound (and also as we get
# up to speed). We stop almost immediately on gel too.
file.write(MUSIC_GEL_STACK.format(fadein=0.5, fadeout=0.1))
return file.getvalue().encode()
示例12: res_antlaser
# 需要导入模块: from srctools import Property [as 别名]
# 或者: from srctools.Property import find_key [as 别名]
def res_antlaser(vmf: VMF, res: Property):
"""The condition to generate AntLasers.
This is executed once to modify all instances.
"""
conf_inst = instanceLocs.resolve(res['instance'])
conf_glow_height = Vec(z=res.float('GlowHeight', 48) - 64)
conf_las_start = Vec(z=res.float('LasStart') - 64)
conf_rope_off = res.vec('RopePos')
conf_toggle_targ = res['toggleTarg', '']
beam_conf = res.find_key('BeamKeys', [])
glow_conf = res.find_key('GlowKeys', [])
cable_conf = res.find_key('CableKeys', [])
if beam_conf:
# Grab a copy of the beam spawnflags so we can set our own options.
conf_beam_flags = beam_conf.int('spawnflags')
# Mask out certain flags.
conf_beam_flags &= (
0
| 1 # Start On
| 2 # Toggle
| 4 # Random Strike
| 8 # Ring
| 16 # StartSparks
| 32 # EndSparks
| 64 # Decal End
#| 128 # Shade Start
#| 256 # Shade End
#| 512 # Taper Out
)
else:
conf_beam_flags = 0
conf_outputs = [
Output.parse(prop)
for prop in res
if prop.name in ('onenabled', 'ondisabled')
]
# Find all the markers.
nodes = {} # type: Dict[str, Item]
for inst in vmf.by_class['func_instance']:
if inst['file'].casefold() not in conf_inst:
continue
name = inst['targetname']
try:
# Remove the item - it's no longer going to exist after
# we're done.
nodes[name] = connections.ITEMS.pop(name)
except KeyError:
raise ValueError('No item for "{}"?'.format(name)) from None
if not nodes:
# None at all.
return conditions.RES_EXHAUSTED
# Now find every connected group, recording inputs, outputs and links.
todo = set(nodes.values())
groups = [] # type: List[Group]
# Node -> is grouped already.
node_pairing = dict.fromkeys(nodes.values(), False)
while todo:
start = todo.pop()
# Synthesise the Item used for logic.
# We use a random info_target to manage the IO data.
group = Group(start)
groups.append(group)
for node in group.nodes:
# If this node has no non-node outputs, destroy the antlines.
has_output = False
node_pairing[node] = True
for conn in list(node.outputs):
neighbour = conn.to_item
todo.discard(neighbour)
pair_state = node_pairing.get(neighbour, None)
if pair_state is None:
# Not a node, a target of our logic.
conn.from_item = group.item
has_output = True
continue
elif pair_state is False:
# Another node.
group.nodes.append(neighbour)
# else: True, node already added.
# For nodes, connect link.
conn.remove()
group.links.add(frozenset({node, neighbour}))
# If we have a real output, we need to transfer it.
# Otherwise we can just destroy it.
if has_output:
node.transfer_antlines(group.item)
#.........这里部分代码省略.........
示例13: parse
# 需要导入模块: from srctools import Property [as 别名]
# 或者: from srctools.Property import find_key [as 别名]
def parse(cls, conf: Property):
"""Read in a fizzler from a config."""
fizz_id = conf['id']
item_ids = [
prop.value.casefold()
for prop in
conf.find_all('item_id')
]
try:
model_name_type = ModelName(conf['NameType', 'same'].casefold())
except ValueError:
LOGGER.warning('Bad model name type: "{}"', conf['NameType'])
model_name_type = ModelName.SAME
model_local_name = conf['ModelName', '']
if not model_local_name:
# We can't rename without a local name.
model_name_type = ModelName.SAME
inst = {}
for inst_type, is_static in itertools.product(FizzInst, (False, True)):
inst_type_name = inst_type.value + ('_static' if is_static else '')
inst[inst_type, is_static] = instances = [
file
for prop in conf.find_all(inst_type_name)
for file in instanceLocs.resolve(prop.value)
]
# Allow specifying weights to bias model locations
weights = conf[inst_type_name + '_weight', '']
if weights:
# Produce the weights, then process through the original
# list to build a new one with repeated elements.
inst[inst_type, is_static] = instances = [
instances[i]
for i in conditions.weighted_random(len(instances), weights)
]
# If static versions aren't given, reuse non-static ones.
# We do False, True so it's already been calculated.
if not instances and is_static:
inst[inst_type, True] = inst[inst_type, False]
if not inst[FizzInst.BASE, False]:
LOGGER.warning('No base instance set! for "{}"!', fizz_id)
voice_attrs = []
for prop in conf.find_all('Has'):
if prop.has_children():
for child in prop:
voice_attrs.append(child.name.casefold())
else:
voice_attrs.append(prop.value.casefold())
pack_lists = {
prop.value
for prop in
conf.find_all('Pack')
}
pack_lists_static = {
prop.value
for prop in
conf.find_all('PackStatic')
}
brushes = [
FizzlerBrush.parse(prop)
for prop in
conf.find_all('Brush')
]
beams = [] # type: List[FizzBeam]
for beam_prop in conf.find_all('Beam'):
offsets = [
Vec.from_str(off.value)
for off in
beam_prop.find_all('pos')
]
keys = Property('', [
beam_prop.find_key('Keys', []),
beam_prop.find_key('LocalKeys', [])
])
beams.append(FizzBeam(
offsets,
keys,
beam_prop.int('RandSpeedMin', 0),
beam_prop.int('RandSpeedMax', 0),
))
try:
temp_conf = conf.find_key('TemplateBrush')
except NoKeyError:
temp_brush_keys = temp_min = temp_max = temp_single = None
else:
temp_brush_keys = Property('--', [
temp_conf.find_key('Keys'),
temp_conf.find_key('LocalKeys', []),
])
# Find and load the templates.
temp_min = temp_conf['Left', None]
#.........这里部分代码省略.........