예제 #1
0
    def parse(cls, vmf: VMF, ent: Entity, radius: float) -> 'Dropper':
        """Scan the map applying dropper tweaks, then create the Dropper object."""
        filter_name = ent['filtername']
        template_name = ent['template']

        for cube_filter in vmf.search(filter_name):
            break
        else:
            raise ValueError(
                f'No filter "{filter_name}" for dropper at {ent["origin"]}!')

        for template in vmf.search(template_name):
            break
        else:
            raise ValueError(
                f'No template "{template_name}" for dropper at {ent["origin"]}!'
            )

        best_cube = None
        best_dist = math.inf
        radius **= 2
        ref_pos = Vec.from_str(cube_filter['origin'])
        for cube in vmf.by_class['prop_weighted_cube'] | vmf.by_class[
                'prop_monster_box']:
            dist = (Vec.from_str(cube['origin']) - ref_pos).mag_sq()
            if dist > radius or dist > best_dist:
                continue
            best_dist = dist
            best_cube = cube
        if best_cube is None:
            LOGGER.warning(
                'Cube dropper at {} has no cube. Generating standard one...',
                ref_pos)
            best_cube = vmf.create_ent(
                'prop_weighted_cube',
                angles='0 0 0',
                newskins='1',
                skintype='0',
                cubetype='0',
                skin='0',
                paintpower='4',
                model=CUBE_MODEL,
            )

        # Now adjust the cube for dropper use.
        best_cube.make_unique('dropper_cube')
        best_cube['origin'] = ent['origin']
        # Only regular cubes can disable funnelling, but frankenturrets
        # require being in box form.
        if best_cube['classname'] == 'prop_monster_box':
            best_cube['startasbox'] = '1'
        else:
            best_cube['allowfunnel'] = '0'

        # Copy the cube name to filter and dropper.
        cube_filter['filtername'] = best_cube['targetname']

        for i in range(1, 10):
            if not template[f'Template{i:02}']:
                template[f'Template{i:02}'] = best_cube['targetname']
            break
        else:
            raise ValueError(f'No spare slots for template "{template_name}"!')

        # Add fizzle outputs if enabled.
        if srctools.conv_bool(ent['autorespawn']):
            best_cube.outputs += [
                out for out in ent.outputs
                if out.output.casefold() == 'onfizzled'
            ]
        ent.add_out(Output(Dropper.pass_out_name, template, 'ForceSpawn'))
        return Dropper(ent, template, best_cube)