def generate_jig_polygon(loc_a, pos_a, rotation_a, loc_b, pos_b, rotation_b, a_left, a_right, a_front, a_back, b_left, b_right, b_front, b_back, positioning_type=JigPositioning.RelativeToSimB, fallback_routing_surface=None, reverse_nonreletive_sim_orientation=False, **fgl_kwargs): if isinstance(pos_a, sims4.math.Vector2): pos_a = sims4.math.Vector3(pos_a.x, 0, pos_a.y) if isinstance(pos_b, sims4.math.Vector2): pos_b = sims4.math.Vector3(pos_b.x, 0, pos_b.y) sim_a_radians = rotation_a sim_b_radians = rotation_b def _generate_polygon_params(relative_loc, fwd_vec, relative_vec, rot_relative, rot_other): polygon_fwd = relative_loc.transform.orientation.transform_vector(fwd_vec) abs_vec_to_relative_sim = relative_loc.transform.orientation.transform_vector(relative_vec) translation_relative = relative_loc.world_transform.translation fwd_relative = sims4.math.vector3_rotate_axis_angle(polygon_fwd, rot_relative, sims4.math.Vector3.Y_AXIS()) translation_other = translation_relative - abs_vec_to_relative_sim fwd_other = sims4.math.vector3_rotate_axis_angle(polygon_fwd, rot_other, sims4.math.Vector3.Y_AXIS()) routing_surface = relative_loc.routing_surface if relative_loc.parent is not None: routing_surface = relative_loc.parent.routing_surface start_location = routing.Location(relative_loc.world_transform.translation, relative_loc.world_transform.orientation, routing_surface) return (start_location, fwd_relative, translation_relative, fwd_other, translation_other, routing_surface) if positioning_type == JigPositioning.RelativeToSimB: vec_to_relative_sim = pos_b - pos_a (start_location, sim_b_fwd, sim_b_translation, sim_a_fwd, sim_a_translation, routing_surface) = _generate_polygon_params(loc_b, -1*sims4.math.Vector3.Z_AXIS(), vec_to_relative_sim, sim_b_radians, sim_a_radians) else: vec_to_relative_sim = pos_a - pos_b (start_location, sim_a_fwd, sim_a_translation, sim_b_fwd, sim_b_translation, routing_surface) = _generate_polygon_params(loc_a, sims4.math.Vector3.Z_AXIS(), vec_to_relative_sim, sim_a_radians, sim_b_radians) polygon = _generate_poly_points(sim_a_translation, sim_a_fwd, sim_b_translation, sim_b_fwd, a_left, a_right, a_front, a_back, b_left, b_right, b_front, b_back) context = placement.FindGoodLocationContext(start_location, object_polygons=(polygon,), **fgl_kwargs) (new_translation, new_orientation) = placement.find_good_location(context) if new_translation is None: if fallback_routing_surface is not None: start_location.routing_surface = fallback_routing_surface context = placement.FindGoodLocationContext(start_location, object_polygons=(polygon,), **fgl_kwargs) (new_translation, new_orientation) = placement.find_good_location(context) if new_translation is None: return (None, None, None, None, None) if positioning_type == JigPositioning.RelativeToSimB: sim_b_translation = new_translation sim_b_orientation = sims4.math.Quaternion.concatenate(new_orientation, sims4.math.angle_to_yaw_quaternion(sim_b_radians)) if reverse_nonreletive_sim_orientation: sim_a_fwd = new_orientation.transform_vector(vec_to_relative_sim) else: sim_a_fwd = new_orientation.transform_vector(-1*vec_to_relative_sim) sim_a_translation = new_translation + new_orientation.transform_vector(-1*vec_to_relative_sim) sim_a_orientation = sims4.math.Quaternion.from_forward_vector(sims4.math.vector3_rotate_axis_angle(sim_a_fwd, sim_a_radians, sims4.math.Vector3.Y_AXIS())) else: sim_a_translation = new_translation sim_a_orientation = sims4.math.Quaternion.concatenate(new_orientation, sims4.math.angle_to_yaw_quaternion(sim_a_radians)) if reverse_nonreletive_sim_orientation: sim_b_fwd = new_orientation.transform_vector(vec_to_relative_sim) else: sim_b_fwd = new_orientation.transform_vector(-1*vec_to_relative_sim) sim_b_translation = new_translation + new_orientation.transform_vector(-1*vec_to_relative_sim) sim_b_orientation = sims4.math.Quaternion.concatenate(new_orientation, sims4.math.angle_to_yaw_quaternion(sim_b_radians)) return (sim_a_translation, sim_a_orientation, sim_b_translation, sim_b_orientation, routing_surface)
def get_slot_pos(self, index=None): participant = self.get_participant() trans = None if participant is not None: (trans, _) = placement.find_good_location( placement.FindGoodLocationContext( starting_location=participant.location, max_distance=FGLTuning.MAX_FGL_DISTANCE, additional_avoid_sim_radius=routing. get_default_agent_radius(), object_id=participant.id, max_steps=10, offset_distance=self.distance_to_participant, scoring_functions=(placement.ScoringFunctionRadial( participant.location.transform.translation, self.distance_to_participant, 0, FGLTuning.MAX_FGL_DISTANCE), ), search_flags=placement.FGLSearchFlag. STAY_IN_CONNECTED_CONNECTIVITY_GROUP | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY | placement.FGLSearchFlag.USE_SIM_FOOTPRINT | placement.FGLSearchFlag.CALCULATE_RESULT_TERRAIN_HEIGHTS)) if trans is None: fallback_point = services.current_zone().get_spawn_point( lot_id=self.lot_id) (trans, _) = fallback_point.next_spawn_spot() return trans return trans
def _get_terrain_transform(self, interaction): if self.owner.footprint_component is not None: sim = interaction.sim additional_put_down_distance = sim.posture_state.body.additional_put_down_distance starting_position = sim.position + sim.forward * ( sim.object_radius + additional_put_down_distance) sim_los_constraint = sim.lineofsight_component.constraint if not sims4.geometry.test_point_in_compound_polygon( starting_position, sim_los_constraint.geometry.polygon): starting_position = sim.position search_flags = FGLSearchFlag.STAY_IN_CURRENT_BLOCK | FGLSearchFlag.SHOULD_TEST_ROUTING | FGLSearchFlag.CALCULATE_RESULT_TERRAIN_HEIGHTS | FGLSearchFlag.DONE_ON_MAX_RESULTS | FGLSearchFlag.SHOULD_TEST_BUILDBUY MAX_PUTDOWN_STEPS = 8 MAX_PUTDOWN_DISTANCE = 10 (position, orientation) = placement.find_good_location( placement.FindGoodLocationContext( starting_position=starting_position, starting_orientation=sim.orientation, starting_routing_surface=sim.routing_surface, object_footprints=(self.owner.get_footprint(), ), object_id=self.owner.id, max_steps=MAX_PUTDOWN_STEPS, max_distance=MAX_PUTDOWN_DISTANCE, search_flags=search_flags)) if position is not None: put_down_transform = sims4.math.Transform( position, orientation) return put_down_transform
def snap_to_good_location_on_floor(target, starting_transform=None, starting_routing_surface=None): target.visibility = VisibilityState(True, True, True) parent = target.get_parenting_root() if starting_transform is None: starting_transform = parent.transform starting_transform = sims4.math.Transform( parent.position + parent.forward * parent.object_radius, starting_transform.orientation) if starting_routing_surface is None: starting_routing_surface = parent.routing_surface search_flags = CarryingObject.SNAP_TO_GOOD_LOCATION_SEARCH_FLAGS (trans, orient) = placement.find_good_location( placement.FindGoodLocationContext( starting_transform=starting_transform, starting_routing_surface=starting_routing_surface, object_footprints=(target.footprint, ), object_id=target.id, search_flags=search_flags)) if starting_transform is not None and ( starting_transform.translation != trans or starting_transform.orientation != orient): logger.debug( "snap_to_good_location_on_floor's FGL couldn't use the exact suggested starting transform." ) if trans is not None: target.clear_parent(sims4.math.Transform(trans, orient), starting_routing_surface) return True logger.warn( 'snap_to_good_location_on_floor could not find good location for {}.', target) target.clear_parent(starting_transform, starting_routing_surface) return False
def _run_interaction_gen(self, timeline): if not self._teleporting: return True yield starting_loc = placement.create_starting_location( transform=self.target.transform, routing_surface=self.target.routing_surface) if self.target_jig is not None: fgl_context = placement.create_fgl_context_for_object( starting_loc, self.target_jig) else: fgl_context = placement.create_fgl_context_for_sim( starting_loc, self.sim) (position, orientation) = placement.find_good_location(fgl_context) if position is None: return False yield end_transform = sims4.math.Transform(position, orientation) self.sim.routing_component.on_slot = None ending_location = sims4.math.Location(end_transform, self.target.routing_surface) self.sim.location = ending_location self.sim.refresh_los_constraint() return True yield
def get_save_lot_coords_and_level(self): lot_coord_msg = LotCoord() parent = self.parent if parent is not None and parent.is_sim: parent.force_update_routing_location() starting_position = parent.position + parent.forward search_flags = CarryingObject.SNAP_TO_GOOD_LOCATION_SEARCH_FLAGS (trans, orient) = placement.find_good_location(placement.FindGoodLocationContext(starting_position=starting_position, starting_orientation=parent.orientation, starting_routing_surface=self.location.world_routing_surface, object_footprints=(self.footprint,), object_id=self.id, search_flags=search_flags)) if trans is None: logger.warn('Unable to find good location to save object{}, which is parented to sim {} and cannot go into an inventory. Defaulting to location of sim.', self, parent) transform = parent.transform else: transform = sims4.math.Transform(trans, orient) transform = services.current_zone().lot.convert_to_lot_coordinates(transform) elif self.persistence_group == PersistenceGroups.OBJECT: transform = services.current_zone().lot.convert_to_lot_coordinates(self.transform) else: transform = self.transform lot_coord_msg.x = transform.translation.x lot_coord_msg.y = transform.translation.y lot_coord_msg.z = transform.translation.z lot_coord_msg.rot_x = transform.orientation.x lot_coord_msg.rot_y = transform.orientation.y lot_coord_msg.rot_z = transform.orientation.z lot_coord_msg.rot_w = transform.orientation.w if self.location.world_routing_surface is not None: level = self.location.level else: level = 0 return (lot_coord_msg, level)
def _do_behavior(self, *args, **kwargs): subject = self.interaction.get_participant(self.subject) target = self.interaction.get_participant(self.target) if subject is None or target is None: logger.error( 'Trying to run a PutNear basic extra with a None Subject and/or Target. subject:{}, target:{}', subject, target, owner='trevor') return starting_location = placement.create_starting_location( location=target.location) if subject.is_sim: fgl_context = placement.create_fgl_context_for_sim( starting_location, subject) else: fgl_context = placement.create_fgl_context_for_object( starting_location, subject) (translation, orientation) = placement.find_good_location(fgl_context) surface = target.routing_surface if translation is None: if self.fallback_to_spawn_point: zone = services.current_zone() fallback_point = zone.get_spawn_point(lot_id=zone.lot.lot_id) (translation, orientation) = fallback_point.next_spawn_spot() surface = fallback_point.routing_surface if translation is not None: subject.move_to(translation=translation, orientation=orientation or subject.orientation, routing_surface=surface, parent=None, joint_name_or_hash=None, slot_hash=0)
def place_puddle(self, target, max_distance, ids_to_ignore=DEFAULT): destroy_puddle = True try: if ids_to_ignore is DEFAULT: ids_to_ignore = (self.id,) else: ids_to_ignore.append(self.id) flags = placement.FGLSearchFlag.ALLOW_GOALS_IN_SIM_POSITIONS flags = flags | placement.FGLSearchFlag.ALLOW_GOALS_IN_SIM_INTENDED_POSITIONS flags = flags | placement.FGLSearchFlag.STAY_IN_SAME_CONNECTIVITY_GROUP if target.is_on_active_lot(): flags = flags | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY else: flags = flags | placement.FGLSearchFlag.SHOULD_TEST_ROUTING flags = flags | placement.FGLSearchFlag.USE_SIM_FOOTPRINT flags = flags | placement.FGLSearchFlag.CALCULATE_RESULT_TERRAIN_HEIGHTS flags = flags | placement.FGLSearchFlag.DONE_ON_MAX_RESULTS radius_target = target while radius_target.parent is not None: radius_target = radius_target.parent if radius_target.is_part: radius_target = radius_target.part_owner fgl_context = placement.FindGoodLocationContext(starting_position=target.position + target.forward*radius_target.object_radius, starting_orientation=sims4.random.random_orientation(), starting_routing_surface=target.routing_surface, object_id=self.id, ignored_object_ids=ids_to_ignore, max_distance=max_distance, search_flags=flags) (position, orientation) = placement.find_good_location(fgl_context) if position is not None: destroy_puddle = False self.location = sims4.math.Location(sims4.math.Transform(position, orientation), target.routing_surface) self.fade_in() self.start_evaporation() return True return False finally: if destroy_puddle: self.destroy(source=self, cause='Failed to place puddle.')
def _run_interaction_gen(self, timeline): obj = objects.system.create_object(self.test_definition) if obj is not None: obj.move_to(translation=self.context.pick.location) (position, orientation) = placement.find_good_location( placement.FindGoodLocationContext( starting_position=self.context.pick.location, ignored_object_ids=(obj.id, ), object_id=obj.id, position_increment=0.6, search_flags=placement.FGLSearchFlagsDefault | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY | placement.FGLSearchFlag.DONE_ON_MAX_RESULTS | placement.FGLSearchFlag.STAY_IN_CURRENT_BLOCK, object_footprints=(self.test_definition.get_footprint(0), ))) if position is None or orientation is None: if obj is not None: obj.destroy( source=self, cause= 'Failed to find good location in debug find good location interaction.' ) return False loc = sims4.math.Transform(position, orientation) sims4.log.info('Placement', 'Found good location:\n Pos: {0}\n Ori: {1}', position, orientation) if obj is not None: obj.transform = loc return True return False
def _find_germinate_location(self, plant): if self.owner.parent_slot is not None: result = self.owner.parent_slot.is_valid_for_placement( definition=self.plant, objects_to_ignore=(self.owner, )) if not result: return location = self.owner.location else: search_flags = FGLSearchFlagsDefault | FGLSearchFlag.ALLOW_GOALS_IN_SIM_INTENDED_POSITIONS | FGLSearchFlag.ALLOW_GOALS_IN_SIM_POSITIONS | FGLSearchFlag.SHOULD_TEST_BUILDBUY starting_location = create_starting_location( location=self.owner.location) context = FindGoodLocationContext( starting_location, ignored_object_ids=(self.owner.id, ), object_id=plant.id, object_def_state_index=plant.state_index, object_footprints=(plant.get_footprint(), ), search_flags=search_flags) (translation, orientation) = find_good_location(context) if translation is None or orientation is None: return location = sims4.math.Location( sims4.math.Transform(translation, orientation), self.owner.routing_surface) return location
def place_puddle(self, target, max_distance, ids_to_ignore=DEFAULT): destroy_puddle = True try: if ids_to_ignore is DEFAULT: ids_to_ignore = (self.id,) else: ids_to_ignore.append(self.id) flags = placement.FGLSearchFlag.ALLOW_GOALS_IN_SIM_POSITIONS flags = flags | placement.FGLSearchFlag.ALLOW_GOALS_IN_SIM_INTENDED_POSITIONS flags = flags | placement.FGLSearchFlag.STAY_IN_SAME_CONNECTIVITY_GROUP if target.is_on_active_lot(): flags = flags | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY else: flags = flags | placement.FGLSearchFlag.SHOULD_TEST_ROUTING flags = flags | placement.FGLSearchFlag.USE_SIM_FOOTPRINT flags = flags | placement.FGLSearchFlag.CALCULATE_RESULT_TERRAIN_HEIGHTS flags = flags | placement.FGLSearchFlag.DONE_ON_MAX_RESULTS radius_target = target while radius_target.parent is not None: radius_target = radius_target.parent if radius_target.is_part: radius_target = radius_target.part_owner routing_surface = target.routing_surface routing_surface = SurfaceIdentifier(routing_surface.primary_id, routing_surface.secondary_id, SurfaceType.SURFACETYPE_WORLD) starting_location = placement.create_starting_location(position=target.position + target.forward*radius_target.object_radius, orientation=sims4.random.random_orientation(), routing_surface=routing_surface) fgl_context = placement.create_fgl_context_for_object(starting_location, self, search_flags=flags, ignored_object_ids=ids_to_ignore, max_distance=max_distance) (position, orientation) = placement.find_good_location(fgl_context) if position is not None: destroy_puddle = False self.place_puddle_at(position, orientation, routing_surface) return True return False finally: if destroy_puddle: self.destroy(source=self, cause='Failed to place puddle.')
def _calculate_valid_locations(self): self._valid_attractor_positions.clear() for attractor_tuning in self.attractors: terrain_tags = list(attractor_tuning.terrain_tags ) if attractor_tuning.terrain_tags else [] objects_to_ignore = self._attractor_ids[attractor_tuning] sample_points = services.active_lot( ).get_uniform_sampling_of_points(attractor_tuning.samples_per_axis, attractor_tuning.samples_per_axis) for point in sample_points: starting_location_for_sample = placement.create_starting_location( position=point) placement_polygon = sims4.geometry.generate_circle_constraint( attractor_tuning.placement_circle.number_of_sides, point, attractor_tuning.placement_circle.radius) fgl_context = placement.FindGoodLocationContext( starting_location_for_sample, object_polygons=(placement_polygon, ), ignored_object_ids=objects_to_ignore, max_distance=attractor_tuning.placement_radius, terrain_tags=terrain_tags, min_water_depth=attractor_tuning.min_water_depth, max_water_depth=attractor_tuning.max_water_depth, search_flags=placement.FGLSearchFlagsDefault | placement.FGLSearchFlag.ALLOW_GOALS_IN_SIM_POSITIONS | placement.FGLSearchFlag. ALLOW_GOALS_IN_SIM_INTENDED_POSITIONS) (position, orientation) = placement.find_good_location(fgl_context) if position: self._valid_attractor_positions[attractor_tuning].append( (position, orientation))
def _on_fruit_fall_to_ground(self, fruit): plant = self.owner if fruit.parent is not plant: return False if not plant.is_on_active_lot(): return False starting_location = placement.create_starting_location( position=plant.position, routing_surface=plant.routing_surface) fgl_context = placement.create_fgl_context_for_object( starting_location, fruit, ignored_object_ids=(fruit.id, )) (position, orientation) = placement.find_good_location(fgl_context) if position is None or orientation is None: return False fruit.move_to(parent=None, translation=position, orientation=orientation, routing_surface=plant.routing_surface) owner = plant.get_household_owner_id() if owner is not None: fruit.set_household_owner_id(owner) decay_commodity = GardeningTuning.FRUIT_DECAY_COMMODITY fruit.set_stat_value( decay_commodity, GardeningTuning.FRUIT_DECAY_COMMODITY_DROPPED_VALUE) return True
def debug_create_baby(actor_sim, position, gender, routing_surface=None): baby = None try: actor_sim_info = actor_sim.sim_info account = actor_sim.sim_info.account sim_creator = SimCreator(gender=gender, age=Age.BABY, first_name=SimSpawner.get_random_first_name(account, gender == Gender.FEMALE), last_name=SimSpawner.get_family_name_for_gender(account, actor_sim.last_name, gender == Gender.FEMALE)) (sim_info_list, _) = SimSpawner.create_sim_infos((sim_creator,), household=actor_sim_info.household, account=account, zone_id=actor_sim_info.zone_id, creation_source='cheat: debug_create_baby') sim_info = sim_info_list[0] baby_def = Baby.get_default_baby_def() baby = create_object(baby_def, sim_info.sim_id) baby.set_sim_info(sim_info) fgl_context = placement.FindGoodLocationContext(starting_position=position, object_id=baby.id, search_flags=placement.FGLSearchFlagsDefault, object_footprints=(baby.get_footprint(),)) (trans, orient) = placement.find_good_location(fgl_context) if trans is not None: baby.location = sims4.math.Location(sims4.math.Transform(trans, orient), routing_surface) client = services.client_manager().get_client_by_household_id(sim_info.household_id) while client is not None: client.selectable_sims.add_selectable_sim_info(sim_info) except Exception as e: logger.exception('Create baby fail', e) if actor_sim_info.household.sim_in_household(sim_info.sim_id): actor_sim_info.household.remove_sim_info(sim_info) client = services.client_manager().get_client_by_household_id(sim_info.household_id) if client is not None: client.selectable_sims.remove_selectable_sim_info(sim_info) while baby is not None: baby.destroy(source=actor_sim, cause='Create baby fail')
def try_to_place_bassinet(position, **kwargs): fgl_context = placement.FindGoodLocationContext(starting_position=position, object_id=sim_info.sim_id, search_flags=placement.FGLSearchFlagsDefault | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY, object_footprints=(bassinet.get_footprint(),), **kwargs) (translation, orientation) = placement.find_good_location(fgl_context) if translation is not None and orientation is not None: bassinet.move_to(translation=translation, orientation=orientation) return True return False
def _teleport(self): polygon = None if self._constraint.geometry is None else self._constraint.geometry.polygon if polygon: if isinstance(polygon, CompoundPolygon): scoring_functions = [ ScoringFunctionPolygon(cp) for cp in polygon ] else: scoring_functions = (ScoringFunctionPolygon(polygon), ) search_flags = FGLSearchFlagsDefault | FGLSearchFlag.USE_SIM_FOOTPRINT | FGLSearchFlag.SHOULD_TEST_BUILDBUY routing_surface = self._constraint.routing_surface target_object = self._interaction.get_constraint_target( self._interaction.target) if target_object is None: return True else: starting_location = create_starting_location( position=self._constraint.average_position, routing_surface=routing_surface) fgl_context = FindGoodLocationContext( starting_location, scoring_functions=scoring_functions, object_id=target_object.id, object_def_state_index=target_object.state_index, search_flags=search_flags) (translation, orientation) = find_good_location(fgl_context) if translation is not None and orientation is not None: self._interaction.sim.move_to( translation=translation, orientation=orientation, routing_surface=routing_surface) return True return False
def create_object_on_ground(self, source_object, spawner_data, max_distance, force_initialization_spawn): spawn_list = list(spawner_data.object_reference) parent_loc_type = self._get_inherited_spawn_location_type() for obj in spawn_list: if not services.lot_spawner_service_instance().check_spawner_firemeter(): logger.info('SpawnerComponent: Firemeter reached, object {} will not spawn', obj) return created_obj = spawner_data.create_spawned_object(source_object, obj, loc_type=parent_loc_type) if created_obj is None: logger.error('SpawnerComponent: Spawner {} failed to create object: {}', source_object, obj, owner='camilogarcia') return created_obj.opacity = 0 if self.owner.is_on_active_lot(): search_flags = placement.FGLSearchFlagsDefault | FGLSearchFlag.SHOULD_TEST_BUILDBUY fgl_context = placement.FindGoodLocationContext(starting_position=created_obj.position, max_distance=max_distance, search_flags=search_flags, object_id=created_obj.id, height_tolerance=GlobalObjectSpawnerTuning.SPAWN_ON_GROUND_FGL_HEIGHT_TOLERANCE, object_footprints=(created_obj.definition.get_footprint(0),)) else: search_flags = placement.FGLSearchFlagsDefault created_obj.location = sims4.math.Location(sims4.math.Transform(self.owner.position, self.owner.orientation), self.owner.routing_surface) polygon = placement.get_accurate_placement_footprint_polygon(created_obj.position, created_obj.orientation, created_obj.scale, created_obj.get_footprint()) fgl_context = placement.FindGoodLocationContext(starting_position=created_obj.position, max_distance=max_distance, search_flags=search_flags, object_polygons=(polygon,), height_tolerance=GlobalObjectSpawnerTuning.SPAWN_ON_GROUND_FGL_HEIGHT_TOLERANCE, ignored_object_ids=(self.owner.id,)) (position, orientation) = placement.find_good_location(fgl_context) if position is not None: created_obj.location = sims4.math.Location(sims4.math.Transform(position, orientation), source_object.routing_surface) services.lot_spawner_service_instance().register_spawned_object(created_obj) if force_initialization_spawn: force_states = spawner_data.spawner_option.force_initialization_spawn else: force_states = spawner_data.spawner_option.force_states for force_state in force_states: created_obj.set_state(force_state.state, force_state) created_obj.fade_in() else: logger.info('SpawnerComponent: FGL failed, object {} will not spawn for spawner {}', created_obj, self.owner) created_obj.destroy(source=self.owner, cause='SpawnerComponent: FGL failed, object will not spawn.')
def get_save_lot_coords_and_level(self): lot_coord_msg = LotCoord() parent = self.parent if parent is not None and parent.is_sim: parent.force_update_routing_location() starting_position = parent.position + parent.forward starting_location = placement.create_starting_location(position=starting_position, orientation=parent.orientation, routing_surface=self.location.world_routing_surface) fgl_context = placement.create_fgl_context_for_object(starting_location, self) (trans, orient) = placement.find_good_location(fgl_context) if trans is None: logger.warn('Unable to find good location to save object{}, which is parented to sim {} and cannot go into an inventory. Defaulting to location of sim.', self, parent) transform = parent.transform else: transform = sims4.math.Transform(trans, orient) if self.persistence_group == PersistenceGroups.OBJECT: transform = services.current_zone().lot.convert_to_lot_coordinates(transform) elif self.persistence_group == PersistenceGroups.OBJECT: transform = services.current_zone().lot.convert_to_lot_coordinates(self.transform) else: transform = self.transform lot_coord_msg.x = transform.translation.x lot_coord_msg.y = transform.translation.y lot_coord_msg.z = transform.translation.z lot_coord_msg.rot_x = transform.orientation.x lot_coord_msg.rot_y = transform.orientation.y lot_coord_msg.rot_z = transform.orientation.z lot_coord_msg.rot_w = transform.orientation.w if self.location.world_routing_surface is not None: level = self.location.level else: level = 0 return (lot_coord_msg, level)
def teleport(self): if random.random() > self.chance_to_teleport: return if self.required_states is not None: for state in self.required_states: if not self.owner.state_value_active(state): return weights_and_commodities = [(obj_dict.weight, obj_dict.static_commodity, obj_dict.state_change) for obj_dict in self.objects_to_teleport_near] while weights_and_commodities: index = sims4.random._weighted(weights_and_commodities) (_, static_commodity, state_change) = weights_and_commodities.pop(index) motives = set() motives.add(static_commodity) all_objects = list(services.object_manager().valid_objects()) random.shuffle(all_objects) for obj in all_objects: if obj is self.owner: continue if obj.commodity_flags & motives: starting_location = placement.create_starting_location(position=obj.position) if self.owner.is_sim: fgl_context = placement.create_fgl_context_for_sim(starting_location, self.owner) else: fgl_context = placement.create_fgl_context_for_object(starting_location, self.owner) (position, orientation) = placement.find_good_location(fgl_context) if position is not None and orientation is not None: self.owner.transform = sims4.math.Transform(position, orientation) if state_change is not None: obj.set_state(state_change.state, state_change) break
def _create_automatic_objects(self, venue_tuning): zone = services.current_zone() for tag_pair in venue_tuning.automatic_objects: try: existing_objects = set( zone.object_manager.get_objects_with_tag_gen(tag_pair.tag)) while not existing_objects: obj = create_object(tag_pair.default_value) position = zone.lot.corners[1] position += vector_normalize(zone.lot.position - position) fgl_context = FindGoodLocationContext( starting_position=position, object_id=obj.id, ignored_object_ids=(obj.id, ), search_flags=placement.FGLSearchFlagsDefault | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY, object_footprints=(obj.get_footprint(), )) (position, orientation) = find_good_location(fgl_context) if position is not None: obj.location = sims4.math.Location( sims4.math.Transform(position, orientation), routing.SurfaceIdentifier( zone.id, 0, routing.SURFACETYPE_WORLD)) else: obj.destroy( source=zone, cause= 'Failed to place automatic object required by venue.' ) except: logger.error( 'Automatic object {} could not be created in venue {} (zone: {}).', obj_definition, venue_tuning, zone)
def get_slot_pos(self, index=None): participant = self.get_participant() trans = None if participant is not None: (trans, _) = placement.find_good_location(placement.FindGoodLocationContext(starting_location=participant.location, max_distance=FGLTuning.MAX_FGL_DISTANCE, additional_avoid_sim_radius=routing.get_default_agent_radius(), object_id=participant.id, max_steps=10, offset_distance=self.distance_to_participant, scoring_functions=(placement.ScoringFunctionRadial(participant.location.transform.translation, self.distance_to_participant, 0, FGLTuning.MAX_FGL_DISTANCE),), search_flags=placement.FGLSearchFlag.STAY_IN_CONNECTED_CONNECTIVITY_GROUP | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY | placement.FGLSearchFlag.USE_SIM_FOOTPRINT | placement.FGLSearchFlag.CALCULATE_RESULT_TERRAIN_HEIGHTS)) if trans is None: fallback_point = services.current_zone().get_spawn_point(lot_id=self.lot_id) (trans, _) = fallback_point.next_spawn_spot() return trans return trans
def __call__(self, sim): def _abort(vehicle_obj): sim.allow_opacity_change = True sim.fade_in() if vehicle_obj is not None: vehicle_obj.destroy() vehicle = None if sim.sim_info.favorites_tracker is not None: favorites_tracker = sim.sim_info.favorites_tracker definition_manager = services.definition_manager() vehicle_def_id = favorites_tracker.get_favorite_definition_id( self.vehicle_obj_tag) if vehicle_def_id is not None: vehicle_def = definition_manager.get(vehicle_def_id) if vehicle_def is not None: vehicle = objects.system.create_object(vehicle_def) if vehicle is None: if self.fallback_vehicle_def is None: _abort(vehicle) return True vehicle = create_object(self.fallback_vehicle_def) if vehicle is None: _abort(vehicle) return True vehicle.set_household_owner_id(sim.household_id) starting_location = placement.create_starting_location( position=sim.position) fgl_context = placement.create_fgl_context_for_object( starting_location, vehicle) (position, orientation) = placement.find_good_location(fgl_context) if position is None or orientation is None: _abort(vehicle) return True vehicle.transform = sims4.math.Transform(position, orientation) result = vehicle.vehicle_component.push_drive_affordance( sim, priority=Priority.Critical) if result is None: _abort(vehicle) return True if result.interaction is None: logger.warn( "Vehicle's push drive affordance {} resulted in a None interaction. Result: {}.", vehicle.vehicle_component.drive_affordance, result, owner='jmorrow') _abort(vehicle) return True sim.fade_in() vehicle.claim() for situation in services.get_zone_situation_manager().get_all(): if sim in situation.all_sims_in_situation_gen(): situation.manage_vehicle(vehicle) break return True
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if self._target is None: self._start_constraint = Nowhere( 'No target for _WaypointGeneratorPacing') self._los_reference_point = None return self._los_reference_point = self._target.position if self._target.is_terrain: self._los_reference_point = None water_constraint = self.get_water_constraint( self.constraint_parameters.min_water_depth, self.constraint_parameters.max_water_depth) if self.outside_only: self._routing_surface = routing.SurfaceIdentifier( services.current_zone_id(), 0, routing.SurfaceType.SURFACETYPE_WORLD) starting_location = Location(position=self._target.position, routing_surface=self._routing_surface) search_flags = FGLSearchFlagsDefaultForSim | FGLSearchFlag.STAY_OUTSIDE fgl_context = placement.FindGoodLocationContext( starting_location, routing_context=self._context.sim.routing_context, additional_avoid_sim_radius=routing.get_default_agent_radius(), max_results=1, max_steps=10, search_flags=search_flags, min_water_depth=water_constraint.get_min_water_depth(), max_water_depth=water_constraint.get_max_water_depth()) (trans, _) = placement.find_good_location(fgl_context) if trans is not None: geometry = sims4.geometry.RestrictedPolygon( sims4.geometry.CompoundPolygon( sims4.geometry.Polygon((trans, ))), ()) self._start_constraint = SmallAreaConstraint( geometry=geometry, debug_name='WaypointPacingStartingConstraint', routing_surface=self._routing_surface, min_water_depth=water_constraint.get_min_water_depth(), max_water_depth=water_constraint.get_max_water_depth()) else: self._start_constraint = Nowhere( 'WaypointGeneratorPacing requires outside, but we failed to find a good location.' ) else: self._start_constraint = Circle( self._target.position, self.constraint_parameters.object_constraint_radius, routing_surface=self._routing_surface, los_reference_point=self._los_reference_point, min_water_depth=water_constraint.get_min_water_depth(), max_water_depth=water_constraint.get_max_water_depth())
def get_waypoint_constraints_gen(self, routing_agent, waypoint_count): line_length_offset = sims4.math.Vector3(0, 0, self.line_length) object_radius = routing_agent.routing_component.object_radius start = routing_agent.position initial_orientation = sims4.random.random_orientation() end = initial_orientation.transform_vector(line_length_offset) + start polygon = build_rectangle_from_two_points_and_radius( start, end, object_radius) starting_location_for_sample = placement.create_starting_location( position=start, routing_surface=self._routing_surface) water_constraint = self.get_water_constraint( self.fgl_parameters.min_water_depth, self.fgl_parameters.max_water_depth) fgl_context = placement.FindGoodLocationContext( starting_location_for_sample, object_polygons=(polygon, ), ignored_object_ids=[routing_agent.id, self._context.sim.sim_id], max_distance=0, min_water_depth=water_constraint.get_min_water_depth(), max_water_depth=water_constraint.get_max_water_depth()) (_, orientation) = placement.find_good_location(fgl_context) if orientation is None: return final_orientation = sims4.math.Quaternion.concatenate( orientation, initial_orientation) oriented_line_offset = final_orientation.transform_vector( line_length_offset) waypoint_constraints = [] for waypoint_index in range(0, waypoint_count): percent_down_line = waypoint_index / (waypoint_count - 1) goal_positon = oriented_line_offset * percent_down_line + start geometry = sims4.geometry.RestrictedPolygon( sims4.geometry.CompoundPolygon( sims4.geometry.Polygon((goal_positon, ))), ()) constraint = SmallAreaConstraint( geometry=geometry, routing_surface=self._routing_surface, min_water_depth=water_constraint.get_min_water_depth(), max_water_depth=water_constraint.get_max_water_depth()) waypoint_constraints.append(constraint) end = oriented_line_offset + start polygon = build_rectangle_from_two_points_and_radius( start, end, object_radius) self._footprint = PolygonFootprint( polygon, routing_surface=self._routing_surface, cost=routing.get_default_discouragement_cost(), footprint_type=FootprintType.FOOTPRINT_TYPE_OBJECT, enabled=True) routing_agent.routing_component.pathplan_context.ignore_footprint_contour( self._footprint.footprint_id) yield from waypoint_constraints
def try_to_place_bassinet(position, **kwargs): fgl_context = placement.FindGoodLocationContext( starting_position=position, object_id=sim_info.sim_id, search_flags=placement.FGLSearchFlagsDefault | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY, object_footprints=(bassinet.get_footprint(), ), **kwargs) (translation, orientation) = placement.find_good_location(fgl_context) if translation is not None and orientation is not None: bassinet.move_to(translation=translation, orientation=orientation) return True return False
def _find_germinate_location(self, plant): if self.owner.parent_slot is not None: result = self.owner.parent_slot.is_valid_for_placement(definition=self.plant, objects_to_ignore=(self.owner,)) if not result: return location = self.owner.location else: search_flags = FGLSearchFlagsDefault | FGLSearchFlag.ALLOW_GOALS_IN_SIM_INTENDED_POSITIONS | FGLSearchFlag.ALLOW_GOALS_IN_SIM_POSITIONS | FGLSearchFlag.SHOULD_TEST_BUILDBUY context = FindGoodLocationContext(starting_location=self.owner.location, ignored_object_ids=(self.owner.id,), object_id=plant.id, object_footprints=(plant.get_footprint(),), search_flags=search_flags) (translation, orientation) = find_good_location(context) if translation is None or orientation is None: return location = sims4.math.Location(sims4.math.Transform(translation, orientation), self.owner.routing_surface) return location
def create_multiple_objects(number, *obj_ids, _connection=None): manager = services.object_manager() sim = get_optional_target(None, _connection) search_flags = placement.FGLSearchFlagsDefault | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY if sim is not None: starting_position = sim.position routing_surface = sim.routing_surface else: lot = services.active_lot() starting_position = lot.position routing_surface = routing.SurfaceIdentifier(services.current_zone().id, 0, routing.SURFACETYPE_WORLD) with postures.posture_graph.supress_posture_graph_build(): for obj_id in obj_ids: obj_id = int(obj_id) original_obj = None if obj_id in manager: original_obj = manager.get(obj_id) if original_obj is None: return obj_definition_id = original_obj.definition.id created_obj_count = number while created_obj_count > 0: if original_obj.crafting_component is not None: obj = DebugCreateCraftableInteraction.create_craftable( original_obj.crafting_component._crafting_process. recipe, sim) else: obj = objects.system.create_object(obj_definition_id) if obj is not None: fgl_context = placement.FindGoodLocationContext( starting_position=starting_position, object_id=obj.id, search_flags=search_flags, object_footprints=(obj.get_footprint(), )) (position, orientation) = placement.find_good_location(fgl_context) if position is not None and orientation is not None: obj.move_to(translation=position, orientation=orientation, routing_surface=routing_surface) else: obj.destroy( source=obj, cause= 'Failed to find good location for create_multiple_objects' ) created_obj_count -= 1
def _run_interaction_gen(self, timeline): obj = objects.system.create_object(self.test_definition) if obj is not None: obj.move_to(translation=self.context.pick.location) (position, orientation) = placement.find_good_location(placement.FindGoodLocationContext(starting_position=self.context.pick.location, ignored_object_ids=(obj.id,), object_id=obj.id, position_increment=0.6, search_flags=placement.FGLSearchFlagsDefault | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY | placement.FGLSearchFlag.DONE_ON_MAX_RESULTS | placement.FGLSearchFlag.STAY_IN_CURRENT_BLOCK, object_footprints=(self.test_definition.get_footprint(0),))) if position is None or orientation is None: if obj is not None: obj.destroy(source=self, cause='Failed to find good location in debug find good location interaction.') return False loc = sims4.math.Transform(position, orientation) sims4.log.info('Placement', 'Found good location:\n Pos: {0}\n Ori: {1}', position, orientation) if obj is not None: obj.transform = loc return True return False
def _get_terrain_transform(self, interaction): if self.owner.footprint_component is not None: sim = interaction.sim additional_put_down_distance = sim.posture_state.body.additional_put_down_distance starting_position = sim.position + sim.forward*(sim.object_radius + additional_put_down_distance) sim_los_constraint = sim.lineofsight_component.constraint if not sims4.geometry.test_point_in_compound_polygon(starting_position, sim_los_constraint.geometry.polygon): starting_position = sim.position search_flags = FGLSearchFlag.STAY_IN_CURRENT_BLOCK | FGLSearchFlag.SHOULD_TEST_ROUTING | FGLSearchFlag.CALCULATE_RESULT_TERRAIN_HEIGHTS | FGLSearchFlag.DONE_ON_MAX_RESULTS | FGLSearchFlag.SHOULD_TEST_BUILDBUY MAX_PUTDOWN_STEPS = 8 MAX_PUTDOWN_DISTANCE = 10 (position, orientation) = placement.find_good_location(placement.FindGoodLocationContext(starting_position=starting_position, starting_orientation=sim.orientation, starting_routing_surface=sim.routing_surface, object_footprints=(self.owner.get_footprint(),), object_id=self.owner.id, max_steps=MAX_PUTDOWN_STEPS, max_distance=MAX_PUTDOWN_DISTANCE, search_flags=search_flags)) if position is not None: put_down_transform = sims4.math.Transform(position, orientation) return put_down_transform
def find_good_location(location): search_flags = placement.FGLSearchFlagsDefault | placement.FGLSearchFlag.USE_SIM_FOOTPRINT | placement.FGLSearchFlag.SHOULD_TEST_ROUTING starting_location = placement.create_starting_location( location=location) fgl_context = placement.FindGoodLocationContext( starting_location, additional_avoid_sim_radius=routing. get_sim_extra_clearance_distance(), search_flags=search_flags) (trans, _) = placement.find_good_location(fgl_context) if trans is None: return location new_transform = TurboMathUtil.Position.get_transform( trans, TurboMathUtil.Orientation.get_quaternion_identity()) return location.clone(transform=new_transform)
def _place_object_on_ground(self, head_obj, source_obj): starting_location = create_starting_location( location=source_obj.location) search_flags = FGLSearchFlag.ALLOW_GOALS_IN_SIM_INTENDED_POSITIONS | FGLSearchFlag.ALLOW_GOALS_IN_SIM_POSITIONS fgl_context = placement.create_fgl_context_for_object( starting_location, head_obj, search_flags=search_flags, ignored_object_ids=(source_obj.id, )) (translation, orientation) = find_good_location(fgl_context) if translation is None or orientation is None: return False head_obj.move_to(translation=translation, orientation=orientation, routing_surface=source_obj.routing_surface) return True
def _get_pos(self): participant = self._get_participant() trans = None if participant is not None: scoring_function = placement.ScoringFunctionRadial(participant.location.transform.translation, self._distance_to_participant, 0, FGLTuning.MAX_FGL_DISTANCE) search_flags = placement.FGLSearchFlag.STAY_IN_CONNECTED_CONNECTIVITY_GROUP | placement.FGLSearchFlag.USE_SIM_FOOTPRINT | placement.FGLSearchFlag.CALCULATE_RESULT_TERRAIN_HEIGHTS | placement.FGLSearchFlag.SHOULD_TEST_ROUTING starting_location = placement.create_starting_location(position=participant.position, orientation=participant.orientation, routing_surface=self.routing_surface) pos_increment_info = placement.PositionIncrementInfo(position_increment=self.POSITION_INCREMENT, from_exception=False) fgl_context = placement.FindGoodLocationContext(starting_location, max_distance=FGLTuning.MAX_FGL_DISTANCE, additional_avoid_sim_radius=routing.get_default_agent_radius(), max_steps=10, position_increment_info=pos_increment_info, offset_distance=self._distance_to_participant, scoring_functions=(scoring_function,), search_flags=search_flags) (trans, _) = placement.find_good_location(fgl_context) if trans is None: fallback_point = services.current_zone().get_spawn_point(lot_id=self.lot_id) (trans, _) = fallback_point.next_spawn_spot() self._routing_surface_override = fallback_point.routing_surface return trans return trans
def _create_automatic_objects(self, venue_tuning): zone = services.current_zone() for tag_pair in venue_tuning.automatic_objects: try: existing_objects = set(zone.object_manager.get_objects_with_tag_gen(tag_pair.tag)) while not existing_objects: obj = create_object(tag_pair.default_value) position = zone.lot.corners[1] position += vector_normalize(zone.lot.position - position) fgl_context = FindGoodLocationContext(starting_position=position, object_id=obj.id, ignored_object_ids=(obj.id,), search_flags=placement.FGLSearchFlagsDefault | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY, object_footprints=(obj.get_footprint(),)) (position, orientation) = find_good_location(fgl_context) if position is not None: obj.location = sims4.math.Location(sims4.math.Transform(position, orientation), routing.SurfaceIdentifier(zone.id, 0, routing.SURFACETYPE_WORLD)) else: obj.destroy(source=zone, cause='Failed to place automatic object required by venue.') except: logger.error('Automatic object {} could not be created in venue {} (zone: {}).', obj_definition, venue_tuning, zone)
def debug_create_baby(actor_sim, position, gender, routing_surface=None): baby = None try: actor_sim_info = actor_sim.sim_info account = actor_sim.sim_info.account sim_creator = SimCreator( gender=gender, age=Age.BABY, first_name=SimSpawner.get_random_first_name( account, gender == Gender.FEMALE), last_name=SimSpawner.get_family_name_for_gender( account, actor_sim.last_name, gender == Gender.FEMALE)) (sim_info_list, _) = SimSpawner.create_sim_infos( (sim_creator, ), household=actor_sim_info.household, account=account, zone_id=actor_sim_info.zone_id, creation_source='cheat: debug_create_baby') sim_info = sim_info_list[0] baby_def = Baby.get_default_baby_def() baby = create_object(baby_def, sim_info.sim_id) baby.set_sim_info(sim_info) fgl_context = placement.FindGoodLocationContext( starting_position=position, object_id=baby.id, search_flags=placement.FGLSearchFlagsDefault, object_footprints=(baby.get_footprint(), )) (trans, orient) = placement.find_good_location(fgl_context) if trans is not None: baby.location = sims4.math.Location( sims4.math.Transform(trans, orient), routing_surface) client = services.client_manager().get_client_by_household_id( sim_info.household_id) while client is not None: client.selectable_sims.add_selectable_sim_info(sim_info) except Exception as e: logger.exception('Create baby fail', e) if actor_sim_info.household.sim_in_household(sim_info.sim_id): actor_sim_info.household.remove_sim_info(sim_info) client = services.client_manager().get_client_by_household_id( sim_info.household_id) if client is not None: client.selectable_sims.remove_selectable_sim_info(sim_info) while baby is not None: baby.destroy(source=actor_sim, cause='Create baby fail')
def _restore_crate(self): if self._pet_crate_x is None: return obj = create_object(self.pet_crate_object_definition) if obj is None: return position = sims4.math.Vector3(float(self._pet_crate_x), float(self._pet_crate_y), float(self._pet_crate_z)) starting_location = placement.create_starting_location( position=position) fgl_context = placement.create_fgl_context_for_object( starting_location, obj, ignored_object_ids=(obj.id, )) (position, orientation) = placement.find_good_location(fgl_context) if position is not None and orientation is not None: obj.move_to(translation=position, orientation=orientation) else: obj.destroy()
def snap_to_good_location_on_floor(target, starting_transform=None, starting_routing_surface=None): target.visibility = VisibilityState(True, True, True) parent = target.get_parenting_root() if starting_transform is None: starting_transform = parent.transform starting_transform = sims4.math.Transform(parent.position + parent.forward*parent.object_radius, starting_transform.orientation) if starting_routing_surface is None: starting_routing_surface = parent.routing_surface search_flags = CarryingObject.SNAP_TO_GOOD_LOCATION_SEARCH_FLAGS (trans, orient) = placement.find_good_location(placement.FindGoodLocationContext(starting_transform=starting_transform, starting_routing_surface=starting_routing_surface, object_footprints=(target.footprint,), object_id=target.id, search_flags=search_flags)) if starting_transform is not None and (starting_transform.translation != trans or starting_transform.orientation != orient): logger.debug("snap_to_good_location_on_floor's FGL couldn't use the exact suggested starting transform.") if trans is not None: target.clear_parent(sims4.math.Transform(trans, orient), starting_routing_surface) return True logger.warn('snap_to_good_location_on_floor could not find good location for {}.', target) target.clear_parent(starting_transform, starting_routing_surface) return False
def create_collectible_from_lightning_strike(location): create_tuning = LightningTuning.STRIKE_TERRAIN_TUNING.create_object_tuning weighted_items = [(def_weight.weight, def_weight.definition) for def_weight in create_tuning.definition_weights] obj_def = sims4.random.weighted_random_item(weighted_items) search_flags = placement.FGLSearchFlag.STAY_IN_CONNECTED_CONNECTIVITY_GROUP | placement.FGLSearchFlag.CALCULATE_RESULT_TERRAIN_HEIGHTS | placement.FGLSearchFlag.DONE_ON_MAX_RESULTS | placement.FGLSearchFlag.ALLOW_GOALS_IN_SIM_POSITIONS starting_location = placement.create_starting_location(location=location) fgl_context = placement.create_fgl_context_for_object(starting_location, obj_def, search_flags=search_flags) (new_position, new_orientation) = placement.find_good_location(fgl_context) if new_position is None or new_orientation is None: logger.info('No good location found for {} from a lightning strike at {}.', obj_def, location, owner='rmccord') return new_location = sims4.math.Location(sims4.math.Transform(new_position, new_orientation), location.routing_surface) created_obj = objects.system.create_object(obj_def) if created_obj is not None: created_obj.opacity = 0 created_obj.fade_in() created_obj.set_location(new_location) created_obj.set_household_owner_id(None)
def place_puddle(self, target, max_distance, ids_to_ignore=DEFAULT): destroy_puddle = True try: if ids_to_ignore is DEFAULT: ids_to_ignore = (self.id, ) else: ids_to_ignore.append(self.id) flags = placement.FGLSearchFlag.ALLOW_GOALS_IN_SIM_POSITIONS flags = flags | placement.FGLSearchFlag.ALLOW_GOALS_IN_SIM_INTENDED_POSITIONS flags = flags | placement.FGLSearchFlag.STAY_IN_SAME_CONNECTIVITY_GROUP if target.is_on_active_lot(): flags = flags | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY else: flags = flags | placement.FGLSearchFlag.SHOULD_TEST_ROUTING flags = flags | placement.FGLSearchFlag.USE_SIM_FOOTPRINT flags = flags | placement.FGLSearchFlag.CALCULATE_RESULT_TERRAIN_HEIGHTS flags = flags | placement.FGLSearchFlag.DONE_ON_MAX_RESULTS radius_target = target while radius_target.parent is not None: radius_target = radius_target.parent if radius_target.is_part: radius_target = radius_target.part_owner fgl_context = placement.FindGoodLocationContext( starting_position=target.position + target.forward * radius_target.object_radius, starting_orientation=sims4.random.random_orientation(), starting_routing_surface=target.routing_surface, object_id=self.id, ignored_object_ids=ids_to_ignore, max_distance=max_distance, search_flags=flags) (position, orientation) = placement.find_good_location(fgl_context) if position is not None: destroy_puddle = False self.location = sims4.math.Location( sims4.math.Transform(position, orientation), target.routing_surface) self.fade_in() self.start_evaporation() return True return False finally: if destroy_puddle: self.destroy(source=self, cause='Failed to place puddle.')
def _get_terrain_transform(self, interaction): if not self.owner.is_sim and self.owner.footprint_component is None: return (None, None) else: sim = interaction.sim put_down_position = interaction.interaction_parameters.get( 'put_down_position') put_down_routing_surface = interaction.interaction_parameters.get( 'put_down_routing_surface') if put_down_position is None: (starting_position, starting_routing_surface ) = self.get_initial_put_down_position(carrying_sim=sim) else: starting_position = put_down_position starting_routing_surface = put_down_routing_surface starting_location = placement.create_starting_location( position=starting_position, orientation=sim.orientation, routing_surface=starting_routing_surface) if self.owner.is_sim: search_flags = FGLSearchFlagsDefaultForSim | FGLSearchFlag.STAY_IN_CURRENT_BLOCK fgl_context_fn = functools.partial( placement.create_fgl_context_for_sim, search_flags=search_flags) else: search_flags = FGLSearchFlag.STAY_IN_CURRENT_BLOCK | FGLSearchFlag.SHOULD_TEST_ROUTING | FGLSearchFlag.CALCULATE_RESULT_TERRAIN_HEIGHTS | FGLSearchFlag.DONE_ON_MAX_RESULTS | FGLSearchFlag.SHOULD_TEST_BUILDBUY fgl_context_fn = functools.partial( placement.create_fgl_context_for_object, search_flags=search_flags) MAX_PUTDOWN_STEPS = 8 MAX_PUTDOWN_DISTANCE = 10 fgl_context = fgl_context_fn( starting_location, self.owner, max_steps=MAX_PUTDOWN_STEPS, max_distance=MAX_PUTDOWN_DISTANCE, height_tolerance=self.put_down_height_tolerance) (position, orientation) = placement.find_good_location(fgl_context) if position is not None: put_down_transform = sims4.math.Transform( position, orientation) return (put_down_transform, starting_routing_surface) return (None, None)
def get_good_location_on_floor(target, *, starting_transform, starting_routing_surface, additional_search_flags=0): starting_location = placement.create_starting_location( transform=starting_transform, routing_surface=starting_routing_surface) if target.is_sim: search_flags = FGLSearchFlagsDefaultForSim fgl_context_fn = placement.create_fgl_context_for_sim else: search_flags = FGLSearchFlagsDefault fgl_context_fn = placement.create_fgl_context_for_object search_flags |= additional_search_flags fgl_context = fgl_context_fn(starting_location, target, search_flags=search_flags) (translation, orientation) = placement.find_good_location(fgl_context) return (translation, orientation)
def _fall_to_ground(self): self._cancel_fall_to_ground_retry_alarm() if not self.is_on_tree: return if self.owner.in_use: self._fall_to_ground_retry_alarm_handle = alarms.add_alarm(self.owner, TimeSpan.in_real_world_seconds(10), self._fall_to_ground) return parent_obj = self.owner.parent if parent_obj is None: logger.warn('{}: Fruit failed to fall, it is no longer parented.', self.owner) return target_location = routing.Location(self.owner.routing_location.position, parent_obj.routing_location.orientation, parent_obj.routing_location.routing_surface) context = FindGoodLocationContext(starting_routing_location=target_location, object_footprints=(self.plant.get_footprint(0),), max_distance=self.fruit_fall_behavior.search_radius.upper_bound) (translation, orientation) = find_good_location(context) if translation is None or orientation is None: logger.warn('{}: Failed to fall because FGL failed.', self.owner) self.owner.destroy(source=parent_obj, cause='Failed to fall because FGL failed') return if self.owner.parent is not None: self.owner.clear_parent(sims4.math.Transform(translation, orientation), self.owner.routing_surface) else: self.owner.set_location(sims4.math.Location(sims4.math.Transform(translation, orientation), self.owner.routing_surface))
def _place_object_no_fallback(self, created_object): participant = self.interaction.get_participant(self.location.location_target) if self.location.location == self.POSITION: offset_tuning = self.location.offset_tuning default_offset = sims4.math.Vector3(offset_tuning.default_offset.x, offset_tuning.default_offset.y, offset_tuning.default_offset.z) x_range = offset_tuning.x_randomization_range z_range = offset_tuning.z_randomization_range start_orientation = sims4.random.random_orientation() if x_range is not None: x_axis = start_orientation.transform_vector(sims4.math.Vector3.X_AXIS()) default_offset += x_axis*random.uniform(x_range.lower_bound, x_range.upper_bound) if z_range is not None: z_axis = start_orientation.transform_vector(sims4.math.Vector3.Z_AXIS()) default_offset += z_axis*random.uniform(z_range.lower_bound, z_range.upper_bound) offset = sims4.math.Transform(default_offset, sims4.math.Quaternion.IDENTITY()) start_position = sims4.math.Transform.concatenate(offset, participant.transform).translation routing_surface = participant.routing_surface active_lot = services.active_lot() search_flags = placement.FGLSearchFlagsDefault if self.location.allow_off_lot_placement and not active_lot.is_position_on_lot(start_position): created_object.location = sims4.math.Location(sims4.math.Transform(start_position, start_orientation), routing_surface) polygon = placement.get_accurate_placement_footprint_polygon(created_object.position, created_object.orientation, created_object.scale, created_object.get_footprint()) context = placement.FindGoodLocationContext(starting_position=start_position, starting_orientation=start_orientation, starting_routing_surface=routing_surface, ignored_object_ids=(created_object.id,), search_flags=search_flags, object_polygons=(polygon,)) else: if not self.location.ignore_bb_footprints: search_flags |= placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY | placement.FGLSearchFlag.STAY_IN_CURRENT_BLOCK if not active_lot.is_position_on_lot(start_position): start_position = active_lot.get_default_position(position=start_position) context = placement.FindGoodLocationContext(starting_position=start_position, starting_orientation=start_orientation, starting_routing_surface=routing_surface, object_id=created_object.id, ignored_object_ids=self._get_ignored_object_ids(), search_flags=search_flags, object_footprints=(self.definition.get_footprint(0),)) (translation, orientation) = placement.find_good_location(context) if translation is not None: created_object.move_to(routing_surface=routing_surface, translation=translation, orientation=orientation) return True elif self.location.location == self.SLOT: parent_slot = self.location.parent_slot if participant.slot_object(parent_slot=parent_slot, slotting_object=created_object): return True return False
def fgl_and_get_two_person_transforms_for_jig(jig_definition, sim, sim_index, target_sim, target_index, constraint_polygon=None): if constraint_polygon is None: key = (sim.id, sim_index, target_sim.id, target_index) data = target_sim.two_person_social_transforms.get(key) return data else: key = None fgl_context = get_fgl_context_for_jig_definition(jig_definition, sim, target_sim, height_tolerance=FGLTuning.SOCIAL_FGL_HEIGHT_TOLERANCE) if constraint_polygon is not None: if isinstance(constraint_polygon, sims4.geometry.CompoundPolygon): for cp in constraint_polygon: fgl_context.search_strategy.add_scoring_function(placement.ScoringFunctionPolygon(cp)) else: fgl_context.search_strategy.add_scoring_function(placement.ScoringFunctionPolygon(constraint_polygon)) (position, orientation) = placement.find_good_location(fgl_context) if position is None or orientation is None: result = (None, None, None) else: jig_transform = sims4.math.Transform(position, orientation) result = get_two_person_transforms_for_jig(jig_definition, jig_transform, target_sim.routing_surface, sim_index, target_index) if key is not None: target_sim.two_person_social_transforms[key] = result return result