def create_put_down_in_inventory_constraint(inst, sim, target, targets_with_inventory, cost=0): if cost is None or not targets_with_inventory: return Nowhere( 'No Cost({}) or No Targets with an inventory of the correct type. Sim: {} Target: {}', cost, sim, target) carry_constraint = create_carry_constraint( target, debug_name='CarryForPutDownInInventory') carry_constraint = carry_constraint.generate_constraint_with_cost(cost) object_constraints = [] for target_with_inventory in targets_with_inventory: if target_with_inventory.item_location == ItemLocation.SIM_INVENTORY: continue constraint = target_with_inventory.get_inventory_access_constraint( sim, True, target) if constraint is None: logger.error( '{} failed to get inventory access constraint for {}, \n If you cannot put down objects in this inventory, you should uncheck: Components -> Inventory -> Allow Putdown In Inventory.\n If you can, you need to properly tune GetPut', sim, target, owner='tastle') return Nowhere( 'Failed Inventory Access Constraint: See Gameplay Console for error.' ) constraint = constraint.apply_posture_state( None, inst.get_constraint_resolver(None)) object_constraints.append(constraint) final_constraint = create_constraint_set(object_constraints) final_constraint = carry_constraint.intersect(final_constraint) return final_constraint
def _run_interaction_gen(self, timeline): result = yield super()._run_interaction_gen(timeline) if not result: return False if self._privacy is not None: constraint_to_satisfy = yield self._create_constraint_set( self.context.sim, timeline) constraint_to_satisfy = Nowhere() logger.warn( 'Failed to generate a valid Shoo constraint. Defaulting to Nowhere().' ) else: logger.error( 'Trying to create a BuildAndForceSatisfyShooConstraintInteraction without a valid privacy instance.', owner='tastle') constraint_to_satisfy = Nowhere() context = self.context.clone_for_continuation(self) constraint_to_satisfy = constraint_to_satisfy.intersect( STAND_CONSTRAINT) result = self.sim.push_super_affordance( ForceSatisfyConstraintSuperInteraction, None, context, allow_posture_changes=True, constraint_to_satisfy=constraint_to_satisfy, name_override='ShooFromPrivacy') if not result: logger.debug( 'Failed to push ForceSatisfyConstraintSuperInteraction on Sim {} to route them out of a privacy area. Result: {}', self.sim, result, owner='tastle') return result
def _create_floor_feature_constraint_set(cls, inst, sim): inst_or_cls = inst if inst is not None else cls floor_feature_contraints = [] floor_features_and_surfaces = [] zone_id = services.current_zone_id() floor_features = build_buy.list_floor_features(inst_or_cls.terrain_feature) if floor_features is None: return Nowhere('No found floor features.') radius_object = None if inst_or_cls.radius_filter is not None: radius_object = inst_or_cls.get_participant(inst_or_cls.radius_filter.radius_actor) if inst_or_cls.radius_filter is not None and radius_object is None: return Nowhere('Radius filter is enabled but the radius actor has a None value.') for floor_feature in floor_features: if inst_or_cls.indoors_only and build_buy.is_location_natural_ground(floor_feature[0], floor_feature[1]): continue routing_surface = routing.SurfaceIdentifier(zone_id, floor_feature[1], routing.SurfaceType.SURFACETYPE_WORLD) floor_feature_location = floor_feature[0] if inst_or_cls.radius_filter is not None: if (radius_object.position - floor_feature_location).magnitude_squared() <= inst_or_cls.radius_filter.radius: floor_features_and_surfaces.append((floor_feature_location, routing_surface)) floor_features_and_surfaces.append((floor_feature_location, routing_surface)) else: floor_features_and_surfaces.append((floor_feature_location, routing_surface)) if floor_features_and_surfaces: for floor_feature_and_surface in floor_features_and_surfaces: circle_constraint = inst_or_cls.routing_circle_constraint.create_constraint(sim, None, target_position=floor_feature_and_surface[0], routing_surface=floor_feature_and_surface[1]) facing_constraint = inst_or_cls.routing_facing_constraint.create_constraint(sim, None, target_position=floor_feature_and_surface[0], routing_surface=floor_feature_and_surface[1]) constraint = circle_constraint.intersect(facing_constraint) floor_feature_contraints.append(constraint) return create_constraint_set(floor_feature_contraints) return Nowhere('With radius filter enabled, no found floor features are within range.')
def generate_constraint(self, build_convex=DEFAULT): self._distance_map = [None] * self._map_divisions self._connection_map = [None] * self._map_divisions self._connection_index = 0 self._collect_segments() vertices = self._render_vertices() segments = self._simplify_geometry(vertices) if build_convex is DEFAULT: build_convex = self.build_convex if build_convex: try: convex_segments = list(self.maximal_convex(vertices)) except RuntimeError as ex: logger.error('{}: {}'.format( ex, ','.join(str(v) for v in vertices))) self._constraint_convex = Nowhere() return simple_convex = self._simplify_geometry(convex_segments) maximal_convex_polygon = self._make_compound_polygon( [simple_convex]) self._constraint_convex = Constraint( debug_name='LineOfSightConvex', routing_surface=self._routing_surface, geometry=sims4.geometry.RestrictedPolygon( maximal_convex_polygon, [])) else: maximal_convex_polygon = None self._constraint_convex = Nowhere() convex_polygons = self._concave_to_convex(segments) cp = self._make_compound_polygon(convex_polygons) self._constraint = Constraint( debug_name='LineOfSight', routing_surface=self._routing_surface, geometry=sims4.geometry.RestrictedPolygon(cp, []))
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 _constraint_gen(cls, inst, sim, target, **kwargs): inst_or_cls = inst if inst is not None else cls yield from super(__class__, inst_or_cls)._constraint_gen(sim, target, **kwargs) if inst is not None: inst._slot_constraint = create_put_down_in_slot_type_constraint( sim, target, inst._slot_types_and_costs) inst._world_constraint = create_put_down_on_ground_constraint( sim, target, inst._terrain_transform, cost=inst._world_cost) inst._sim_inventory_constraint = create_put_down_in_self_inventory_constraint( inst, sim, target, cost=inst._sim_inventory_cost) inst._object_inventory_constraint = create_put_down_in_inventory_constraint( inst, sim, target, targets_with_inventory=inst._objects_with_inventory, cost=inst._object_inventory_cost) if inst._slot_constraint.valid or ( inst._world_constraint.valid or inst._sim_inventory_constraint.valid ) or inst._object_inventory_constraint.valid: constraints = [ inst._slot_constraint, inst._world_constraint, inst._sim_inventory_constraint, inst._object_inventory_constraint ] final_constraint = create_constraint_set(constraints) else: final_constraint = Nowhere( 'PutDownAnywhere could not create any valid putdown constraint.' ) yield final_constraint
def make_constraint_default(cls, actor, target_sim, position, routing_surface, participant_type=ParticipantType.Actor, picked_object=None, participant_slot_overrides=None): if participant_type not in (ParticipantType.Actor, ParticipantType.TargetSim): return Anywhere() all_transforms = [] for (actor_transform, target_transform, routing_surface, _) in cls._get_jig_transforms_gen( actor, target_sim, picked_object=picked_object, participant_slot_overrides=participant_slot_overrides): if participant_type == ParticipantType.Actor: transform = actor_transform else: transform = target_transform if transform is None: continue all_transforms.append( interactions.constraints.Transform( transform, routing_surface=routing_surface, debug_name='JigGroupConstraint')) if not all_transforms: return Nowhere('Unable to get constraints from jig.') return create_constraint_set(all_transforms)
def get_constraint(self, sim, node, var_map): carry_target = var_map[PostureSpecVariable.CARRY_TARGET] parent_slot = var_map.get(PostureSpecVariable.SLOT) if PostureSpecVariable.SLOT not in var_map: from interactions.constraints import Nowhere return Nowhere() if parent_slot is None or not isinstance(parent_slot, RuntimeSlot): if isinstance(parent_slot, animation.posture_manifest.SlotManifestEntry): for parent_slot in self._surface_target.get_runtime_slots_gen( slot_types=parent_slot.slot_types): break raise RuntimeError( 'Failed to resolve slot on {} of type {}'.format( self._surface_target, parent_slot.slot_types)) else: for parent_slot in self._surface_target.get_runtime_slots_gen( slot_types={parent_slot}): break raise RuntimeError( 'Failed to resolve slot on {} of type {}'.format( self._surface_target, {parent_slot})) from carry.carry_postures import CarrySystemRuntimeSlotTarget carry_system_target = CarrySystemRuntimeSlotTarget( sim, carry_target, True, parent_slot) return carry_system_target.get_constraint(sim)
def make_constraint_default(cls, actor, target_sim, position, routing_surface, participant_type=ParticipantType.Actor, picked_object=None, participant_slot_overrides=None): (actor_transform, target_transform, routing_surface) = cls._get_jig_transforms( actor, target_sim, picked_object=picked_object, participant_slot_overrides=participant_slot_overrides) if actor_transform is None or target_transform is None: return Nowhere() if participant_type == ParticipantType.Actor: constraint_transform = actor_transform elif participant_type == ParticipantType.TargetSim: constraint_transform = target_transform else: return Anywhere() return interactions.constraints.Transform( constraint_transform, routing_surface=routing_surface, debug_name='JigGroupConstraint')
def create_put_down_in_slot_type_constraint(sim, target, slot_types_and_costs): constraints = [] for (slot_type, cost) in slot_types_and_costs: if cost is None: pass slot_manifest_entry = SlotManifestEntry(target, PostureSpecVariable.ANYTHING, slot_type) slot_manifest = SlotManifest((slot_manifest_entry, )) posture_state_spec_stand = PostureStateSpec( STAND_POSTURE_MANIFEST, slot_manifest, PostureSpecVariable.ANYTHING) posture_constraint_stand = Constraint( debug_name='PutDownInSlotTypeConstraint_Stand', posture_state_spec=posture_state_spec_stand, cost=cost) constraints.append(posture_constraint_stand) posture_state_spec_sit = PostureStateSpec(SIT_POSTURE_MANIFEST, slot_manifest, PostureSpecVariable.ANYTHING) posture_constraint_sit = Constraint( debug_name='PutDownInSlotTypeConstraint_Sit', posture_state_spec=posture_state_spec_sit, cost=cost) constraints.append(posture_constraint_sit) if not constraints: return Nowhere() final_constraint = create_constraint_set(constraints) return final_constraint
def create_constraint(self, sim, target=None, target_position=DEFAULT, routing_surface=DEFAULT, **kwargs): if target is None: target = sim if routing_surface is DEFAULT: routing_surface = target.intended_routing_surface plex_service = services.get_plex_service() zone_id = services.current_zone_id() if not plex_service.is_zone_a_plex(zone_id): return self.non_plex_constraint.constraint level = routing_surface.secondary_id polygons = plex_service.get_plex_polygons(level) if not polygons: return Nowhere('PlexConstraint: plex {} not on level {}', zone_id, level) compound_polygon = CompoundPolygon(polygons) restricted_polygon = RestrictedPolygon(compound_polygon, []) constraint = Constraint( geometry=restricted_polygon, routing_surface=routing_surface, debug_name='Plex zone id: {}, level: {}'.format(zone_id, level)) return constraint
def _create_social_geometry(self, *args, **kwargs): self._sim_transform_map = defaultdict(list) self.geometry = None for (sim_transform, target_transform, routing_surface, locked_params) in self._get_jig_transforms_gen( self.initiating_sim, self.target_sim, picked_object=self.picked_object, participant_slot_overrides=self.participant_slot_overrides): if not sim_transform is None: if target_transform is None: continue self._sim_transform_map[self.initiating_sim].append( (sim_transform, locked_params)) self._sim_transform_map[self.target_sim].append( (target_transform, ())) if not (self._sim_transform_map[self.initiating_sim] and self._sim_transform_map[self.target_sim]): self._constraint = Nowhere( 'JigGroup, failed to FGL and place the jig. Sim: {}, Target Sim: {}, Picked Object: {}', self.initiating_sim, self.target_sim, self.picked_object) return target_forward = target_transform.transform_vector( sims4.math.FORWARD_AXIS) self._set_focus(target_transform.translation, target_forward, routing_surface, refresh_geometry=False) self._initialize_constraint(notify=True)
def get_constraint(self, sim): transform = self._sim_transform_map.get(sim, None) if transform is not None: return interactions.constraints.Transform( transform, routing_surface=self.routing_surface) if sim in self._sim_transform_map: return Nowhere() return Anywhere()
def apply_posture_state(self, posture_state, participant_type=ParticipantType.Actor, **kwargs): if participant_type == ParticipantType.TargetSim: (target_si, test_result) = self.get_target_si() if target_si is not None and not test_result and posture_state is not None: posture_state.add_constraint(target_si, Nowhere()) if target_si is not None: return target_si.apply_posture_state(posture_state, participant_type=ParticipantType.Actor, **kwargs) return super().apply_posture_state(posture_state, participant_type=participant_type, **kwargs)
def _run_interaction_gen(self, timeline): result = yield super()._run_interaction_gen(timeline) if not result: return False if self._privacy is not None: constraint_to_satisfy = yield self._create_constraint_set(self.context.sim, timeline) constraint_to_satisfy = Nowhere() logger.warn('Failed to generate a valid Shoo constraint. Defaulting to Nowhere().') else: logger.error('Trying to create a BuildAndForceSatisfyShooConstraintInteraction without a valid privacy instance.', owner='tastle') constraint_to_satisfy = Nowhere() context = self.context.clone_for_continuation(self) constraint_to_satisfy = constraint_to_satisfy.intersect(STAND_CONSTRAINT) result = self.sim.push_super_affordance(ForceSatisfyConstraintSuperInteraction, None, context, allow_posture_changes=True, constraint_to_satisfy=constraint_to_satisfy, name_override='ShooFromPrivacy') if not result: logger.debug('Failed to push ForceSatisfyConstraintSuperInteraction on Sim {} to route them out of a privacy area. Result: {}', self.sim, result, owner='tastle') return result
def apply_posture_state_and_interaction_to_constraint(cls, inst, posture_state, intersection, participant_type=ParticipantType.Actor, **kwargs): if inst is None: return intersection.apply_posture_state(posture_state, cls.get_constraint_resolver(posture_state, participant_type=participant_type, **kwargs)) if participant_type == ParticipantType.TargetSim: (target_si, test_result) = inst.get_target_si() if not test_result: return Nowhere() if target_si is not None and (posture_state is None or posture_state.sim is target_si.sim): return target_si.apply_posture_state_and_interaction_to_constraint(posture_state, intersection, participant_type=ParticipantType.Actor, **kwargs) inst_or_cls = inst if inst is not None else cls return super(SuperInteraction, inst_or_cls).apply_posture_state_and_interaction_to_constraint(posture_state, intersection, participant_type=participant_type, **kwargs)
def create_put_down_on_ground_constraint(sim, target, terrain_transform, cost=0): if cost is None or terrain_transform is None: return Nowhere() swipe_constraint = CarryingObject.get_carry_transition_position_constraint( terrain_transform.translation, sim.routing_surface) carry_constraint = create_carry_constraint( target, debug_name='CarryForPutDownOnGround') final_constraint = swipe_constraint.intersect(carry_constraint).intersect( STAND_OR_SIT_CONSTRAINT) return final_constraint.generate_constraint_with_cost(cost)
def _constraint_gen(cls, inst, sim, *args, **kwargs): yield from super()._constraint_gen(sim, *args, **kwargs) if inst is not None and inst._jig_object is not None: jig = inst._jig_object parts = jig.parts part_index = inst._jig_part_index if parts is None: logger.error("{} doesn't have part tuned", jig) yield Nowhere( 'Exception while trying to get routing slot on the jig part.' ) return if part_index >= len(parts): logger.error('{} only have {} parts, out of index {}', jig, len(parts), part_index) yield Nowhere( 'Exception while trying to get routing slot on the jig part.' ) return part = parts[part_index] yield Transform(part.transform, routing_surface=jig.routing_surface)
def create_constraint(self, actor, target, **kwargs): if target is None: return Nowhere( '{} is creating a RoutingSlotConstraint for a None Target.', actor) slot_constraints = [] asm_key = self.animation_element.asm_key actor_name = self.animation_element.actor_name target_name = self.animation_element.target_name state_name = self.animation_element.begin_states[0] asm = create_asm(asm_key, context=get_throwaway_animation_context()) asm.set_actor(actor_name, actor) asm.add_potentially_virtual_actor(actor_name, actor, target_name, target) asm.dirty_boundary_conditions() if actor.is_sim: age = actor.age.age_for_animation_cache else: age = None boundary_conditions = asm.get_boundary_conditions_list( actor, state_name) for (_, slots_to_params_entry) in boundary_conditions: if not slots_to_params_entry: continue slots_to_params_entry_absolute = [] for (boundary_condition_entry, param_sequences_entry) in slots_to_params_entry: (routing_transform_entry, containment_transform, _, reference_joint_exit ) = boundary_condition_entry.get_transforms(asm, target) slots_to_params_entry_absolute.append( (routing_transform_entry, reference_joint_exit, param_sequences_entry)) slot_constraint = RequiredSlotSingle( actor, target, asm, asm_key, None, actor_name, target_name, state_name, containment_transform, None, tuple(slots_to_params_entry_absolute), None, asm_name=asm.name, age=age) slot_constraints.append(slot_constraint) return create_constraint_set(slot_constraints)
def _get_distance_placement_constraint(cls, inst, sim, target, participant_type=ParticipantType. Actor): inst_or_cls = inst if inst is not None else cls if inst is None or participant_type != ParticipantType.Actor: return ANYWHERE constraint = ANYWHERE if inst._distance_placement_transform is None or inst._bounce_transform is None: return Nowhere( "Distance Placement couldn't find a good location for the carry target." ) if inst_or_cls._starting_location is not None: constraint = constraint.intersect( interactions.constraints.Position( inst_or_cls._starting_location.transform.translation, routing_surface=inst_or_cls._starting_location. routing_surface)) else: constraint = constraint.intersect( interactions.constraints.Circle( inst_or_cls._distance_placement_transform.translation, inst_or_cls.placement_distance.upper_bound + DistancePlacementMixin.CONSTRAINT_RADIUS_BUFFER, inst_or_cls.sim.routing_surface, los_reference_point=DEFAULT)) constraint = constraint.intersect( interactions.constraints.Facing( facing_range=inst_or_cls.facing_range, target_position=inst_or_cls._bounce_transform.translation)) if constraint.valid: return constraint return Nowhere( "Distance Placement couldn't find a good location for the carry target." )
def get_constraint(self, sim): transforms = self._sim_transform_map.get(sim, None) if transforms is not None: all_transforms = [ interactions.constraints.Transform( transform, routing_surface=self.routing_surface, create_jig_fn=self._set_sim_intended_location) for (transform, _) in transforms ] return create_constraint_set(all_transforms) if sim in self._sim_transform_map: return Nowhere( "JigGroup, Sim is expected to have a transform but we didn't find a good spot for them. Sim: {}", sim) return Anywhere()
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if self._target is None: self._start_constraint = Nowhere( 'Trying to generate a waypoint constraint without a target.') self._los_reference_point = None else: self._los_reference_point = self._target.position if self._target.is_terrain: self._los_reference_point = None self._start_constraint = Circle( self._target.position, self.object_constraint_radius, routing_surface=self._routing_surface, los_reference_point=self._los_reference_point) self._start_constraint = self._start_constraint.intersect( self.get_water_constraint())
class PlexConstraint(HasTunableSingletonFactory, AutoFactoryInit): FACTORY_TUNABLES = { 'non_plex_constraint': TunableVariant( description= "\n What the behavior of this constraint should be if it's used from\n not a plex.\n ", anywhere=TunableTuple( description= '\n Use Anywhere constraint. This effectively means this plex\n constraint does nothing if the player is not on a plex zone.\n ', locked_args={'constraint': ANYWHERE}), nowhere=TunableTuple( description= '\n Use Nowhere constraint. This effectively makes this plex\n constraint unsatisfiable if the player is not on a plex zone.\n ', locked_args={ 'constraint': Nowhere('PlexConstraint: non-plex zone') }), default='anywhere') } def create_constraint(self, sim, target=None, target_position=DEFAULT, routing_surface=DEFAULT, **kwargs): if target is None: target = sim if routing_surface is DEFAULT: routing_surface = target.intended_routing_surface plex_service = services.get_plex_service() zone_id = services.current_zone_id() if not plex_service.is_zone_a_plex(zone_id): return self.non_plex_constraint.constraint level = routing_surface.secondary_id polygons = plex_service.get_plex_polygons(level) if not polygons: return Nowhere('PlexConstraint: plex {} not on level {}', zone_id, level) compound_polygon = CompoundPolygon(polygons) restricted_polygon = RestrictedPolygon(compound_polygon, []) constraint = Constraint( geometry=restricted_polygon, routing_surface=routing_surface, debug_name='Plex zone id: {}, level: {}'.format(zone_id, level)) return constraint
def create_put_down_in_self_inventory_constraint(inst, sim, target, cost=0): if cost is None: return Nowhere('No Cost({}). Sim: {} Target: {}', cost, sim, target) carry_constraint = create_carry_constraint( target, debug_name='CarryForPutDownInSimInventory') carry_constraint = carry_constraint.generate_constraint_with_cost(cost) constraint = sim.get_inventory_access_constraint(sim, True, target) constraint = constraint.apply_posture_state( None, inst.get_constraint_resolver(None)) posture_slot_constraint = sim.posture.slot_constraint if posture_slot_constraint: if not sim.parent_may_move: constraint = constraint.intersect(posture_slot_constraint) else: constraint = constraint.intersect( Circle(sim.position, PUT_DOWN_GEOMETRY_RADIUS, sim.routing_surface)) final_constraint = carry_constraint.intersect(constraint) return final_constraint
def create_put_down_in_inventory_constraint(inst, sim, target, targets_with_inventory, cost=0): if cost is None or not targets_with_inventory: return Nowhere() carry_constraint = create_carry_constraint( target, debug_name='CarryForPutDownInInventory') carry_constraint = carry_constraint.generate_constraint_with_cost(cost) object_constraints = [] for target_with_inventory in targets_with_inventory: constraint = target_with_inventory.get_inventory_access_constraint( sim, True, target) constraint = constraint.apply_posture_state( None, inst.get_constraint_resolver(None)) object_constraints.append(constraint) final_constraint = create_constraint_set(object_constraints) final_constraint = carry_constraint.intersect(final_constraint) return final_constraint
def __init__(self, *args, si=None, target_sim=None, participant_slot_overrides=None, **kwargs): super().__init__(si=si, target_sim=target_sim, *args, **kwargs) self._sim_transform_map = {} self.geometry = None initiating_sim = si.sim if initiating_sim is None or target_sim is None: logger.error( 'JigGroup {} cannot init with initial sim {()} or target sim {()}', self.__name__, initiating_sim, target_sim) return picked_object = si.picked_object self.participant_slot_overrides = participant_slot_overrides (sim_transform, target_transform, routing_surface) = self._get_jig_transforms( initiating_sim, target_sim, picked_object=picked_object, participant_slot_overrides=self.participant_slot_overrides) self._jig_transform = target_transform if target_transform is not None: self._jig_polygon = placement.get_placement_footprint_polygon( target_transform.translation, target_transform.orientation, routing_surface, self.jig.get_footprint(0)) else: self._jig_polygon = None self._sim_transform_map[initiating_sim] = sim_transform self._sim_transform_map[target_sim] = target_transform if target_transform is None: self._constraint = Nowhere() return target_forward = target_transform.transform_vector( sims4.math.FORWARD_AXIS) self._set_focus(target_transform.translation, target_forward, routing_surface) self._initialize_constraint(notify=True)
def create_put_down_in_slot_type_constraint(sim, carry_target, slot_types_and_costs, target=None): constraints = [] for (slot_type, cost) in slot_types_and_costs: if cost is None: continue if target is not None and target is not carry_target: slot_manifest_entry = SlotManifestEntry( carry_target, PostureSpecVariable.INTERACTION_TARGET, slot_type) else: slot_manifest_entry = SlotManifestEntry( carry_target, PostureSpecVariable.ANYTHING, slot_type) slot_manifest = SlotManifest((slot_manifest_entry, )) posture_state_spec_stand = PostureStateSpec( STAND_POSTURE_MANIFEST, slot_manifest, PostureSpecVariable.ANYTHING) posture_constraint_stand = Constraint( debug_name='PutDownInSlotTypeConstraint_Stand', posture_state_spec=posture_state_spec_stand, cost=cost) constraints.append(posture_constraint_stand) posture_state_spec_sit = PostureStateSpec(SIT_POSTURE_MANIFEST, slot_manifest, PostureSpecVariable.ANYTHING) posture_constraint_sit = Constraint( debug_name='PutDownInSlotTypeConstraint_Sit', posture_state_spec=posture_state_spec_sit, cost=cost) constraints.append(posture_constraint_sit) if not constraints: return Nowhere( 'Carry Target has no slot types or costs tuned for put down: {} Sim:{}', carry_target, sim) final_constraint = create_constraint_set(constraints) return final_constraint
def create_put_down_on_ground_constraint(sim, target, terrain_transform, routing_surface=DEFAULT, cost=0): if cost is None or terrain_transform is None: return Nowhere( 'Put Down On Ground with either no Cost({}) or Transform({}) Sim:{} Target:{}', cost, terrain_transform, sim, target) routing_surface = sim.routing_surface if routing_surface is DEFAULT else routing_surface swipe_constraint = target.get_carry_transition_constraint( sim, terrain_transform.translation, routing_surface) if target.is_sim: if target.should_be_swimming_at_position(terrain_transform.translation, routing_surface.secondary_id, check_can_swim=False): DEFAULT_SIM_PUT_DOWN_OCEAN_CONSTRAINT_RADIUS = 10.0 DEFAULT_SIM_PUT_DOWN_OCEAN_INTERVAL = WaterDepthIntervals.WET start_constraint = OceanStartLocationConstraint.create_simple_constraint( DEFAULT_SIM_PUT_DOWN_OCEAN_INTERVAL, DEFAULT_SIM_PUT_DOWN_OCEAN_CONSTRAINT_RADIUS, target, target_position=terrain_transform.translation, routing_surface=routing_surface) depth_constraint = WaterDepthIntervalConstraint.create_water_depth_interval_constraint( target, DEFAULT_SIM_PUT_DOWN_OCEAN_INTERVAL) swipe_constraint = swipe_constraint.generate_alternate_geometry_constraint( start_constraint.geometry) swipe_constraint = swipe_constraint.generate_alternate_water_depth_constraint( depth_constraint.get_min_water_depth(), depth_constraint.get_max_water_depth()) swipe_constraint = swipe_constraint._copy(_multi_surface=False) carry_constraint = create_carry_constraint( target, debug_name='CarryForPutDownOnGround') final_constraint = swipe_constraint.intersect(carry_constraint).intersect( STAND_AT_NONE_CONSTRAINT) return final_constraint.generate_constraint_with_cost(cost)
def get_combined_constraint(self, existing_constraint=None, priority=None, group_id=None, to_exclude=None, include_inertial_sis=False, force_inertial_sis=False, existing_si=None, posture_state=DEFAULT, allow_posture_providers=True, include_existing_constraint=True, participant_type=ParticipantType.Actor): included_sis = set() if include_inertial_sis: if existing_si is not None and any(si.id == existing_si.continuation_id for si in self): sis_must_include = set() else: sis_must_include = self._get_must_include_sis(priority, group_id, existing_si=existing_si) if force_inertial_sis: for si in self._super_interactions: if si in sis_must_include: continue if not allow_posture_providers and self.sim.posture_state.is_source_interaction(si): continue if not self._common_included_si_tests(si): continue sis_must_include.add(si) to_consider = set() is_like_vehicle = self.sim.posture.is_vehicle or self.sim.parent_may_move for non_guaranteed_si in self._super_interactions: if non_guaranteed_si in sis_must_include: continue if not is_like_vehicle: continue if not allow_posture_providers and (self.sim.posture_state.is_source_interaction(non_guaranteed_si) and self.sim.posture.is_vehicle) and existing_constraint is not None: final_surfaces = {constraint.routing_surface.type for constraint in existing_constraint if constraint.routing_surface is not None} vehicle = self.sim.posture.target vehicle_surfaces = vehicle.vehicle_component.allowed_surfaces if final_surfaces and not any(final_surface in vehicle_surfaces for final_surface in final_surfaces): continue else: to_consider.add(non_guaranteed_si) else: sis_must_include = self._get_must_include_sis(priority, group_id, existing_si=existing_si) to_consider = set() if allow_posture_providers: additional_posture_sis = set() for si in sis_must_include: owned_posture = self.sim.posture_state.get_source_or_owned_posture_for_si(si) if owned_posture is None: continue if owned_posture.track != postures.PostureTrack.BODY: continue source_interaction = owned_posture.source_interaction if not source_interaction is None: if source_interaction.is_finishing: continue additional_posture_sis.add(source_interaction) sis_must_include.update(additional_posture_sis) additional_posture_sis.clear() total_constraint = Anywhere() included_carryables = set() for si_must_include in sis_must_include: if si_must_include.is_finishing: continue if not si_must_include is to_exclude: if si_must_include is existing_si: continue if existing_si is not None and existing_si.group_id == si_must_include.group_id: continue my_role = si_must_include.get_participant_type(self.sim) if existing_si is not None: existing_participant_type = existing_si.get_participant_type(self.sim) if not self.are_sis_compatible(si_must_include, existing_si, my_role, existing_participant_type, ignore_geometry=True): return (Nowhere('SIState.get_combined_constraint, Two SIs are incompatible: SI_A: {}, SI_B: {}', si_must_include, existing_si), sis_must_include) si_constraint = si_must_include.constraint_intersection(participant_type=my_role, posture_state=posture_state) if existing_si is not None: if existing_si.should_rally or existing_si.relocate_main_group: if si_must_include.is_social: if si_must_include.social_group is not None: if si_must_include.social_group is si_must_include.sim.get_main_group(): si_constraint = si_constraint.generate_posture_only_constraint() si_constraint = si_constraint.apply_posture_state(None, existing_si.get_constraint_resolver(None, participant_type=participant_type)) if existing_constraint is not None: si_constraint = si_constraint.apply(existing_constraint) test_constraint = total_constraint.intersect(si_constraint) if not test_constraint.valid: break carry_target = si_must_include.targeted_carryable if carry_target is not None: if len(included_carryables) == 2 and carry_target not in included_carryables: continue included_carryables.add(carry_target) total_constraint = test_constraint included_sis.add(si_must_include) if len(included_carryables) == 2: if existing_si is not None: existing_carry_target = existing_si.carry_target if existing_carry_target is not None: if existing_carry_target not in included_carryables: total_constraint = Nowhere('Cannot include more than two interactions that are carrying objects.') if included_sis != sis_must_include: total_constraint = Nowhere('Unable to combine SIs that are must include.') if not total_constraint.valid: return (total_constraint, included_sis) if total_constraint.tentative or existing_constraint is not None and existing_constraint.tentative: return (total_constraint, included_sis) if to_consider: for si in self._sis_sorted(to_consider): if si is to_exclude: continue if not self._common_included_si_tests(si): continue my_role = si.get_participant_type(self.sim) if existing_si is not None: existing_participant_type = existing_si.get_participant_type(self.sim) if not self.are_sis_compatible(si, existing_si, my_role, existing_participant_type, ignore_geometry=True): continue else: si_constraint = si.constraint_intersection(participant_type=my_role, posture_state=posture_state) if existing_si is not None: si_constraint = si_constraint.apply_posture_state(None, existing_si.get_constraint_resolver(None, participant_type=participant_type)) if si_constraint.tentative: si_constraint = si.constraint_intersection(participant_type=my_role, posture_state=DEFAULT) test_constraint = total_constraint.intersect(si_constraint) if existing_constraint is not None: test_constraint_plus_existing = test_constraint.intersect(existing_constraint) if test_constraint_plus_existing.valid: if test_constraint_plus_existing.tentative: continue test_constraint = test_constraint.apply(existing_constraint) if test_constraint.valid: total_constraint = test_constraint included_sis.add(si) if total_constraint.tentative: break if test_constraint.valid: total_constraint = test_constraint included_sis.add(si) if total_constraint.tentative: break if allow_posture_providers: additional_posture_sis = set() for si in included_sis: owned_posture = self.sim.posture_state.get_source_or_owned_posture_for_si(si) if owned_posture is not None: if owned_posture.source_interaction not in included_sis: if owned_posture.track == postures.PostureTrack.BODY: additional_posture_sis.add(owned_posture.source_interaction) included_sis.update(additional_posture_sis) if include_existing_constraint: if existing_constraint is not None: total_constraint = total_constraint.intersect(existing_constraint) return (total_constraint, included_sis)
def _create_constraint_set(self, sim, timeline): orient = sims4.math.Quaternion.IDENTITY() positions = services.current_zone().lot.corners position = positions[0] routing_surface = self._privacy.constraint.get_world_routing_surface( force_world=True) if self._privacy._routing_surface_only: routing_surfaces = (routing_surface, ) else: routing_surfaces = self._privacy.constraint.get_all_valid_routing_surfaces( ) goals = [] center_pos = services.current_zone().lot.position for pos in positions: plex_service = services.get_plex_service() if plex_service.is_active_zone_a_plex(): towards_center_vec = sims4.math.vector_normalize(center_pos - pos) pos = pos + towards_center_vec * self.PLEX_LOT_CORNER_ADJUSTMENT pos.y = services.terrain_service.terrain_object( ).get_routing_surface_height_at(pos.x, pos.z, routing_surface) if not sims4.geometry.test_point_in_compound_polygon( pos, self._privacy.constraint.geometry.polygon): for surface in routing_surfaces: goals.append( routing.Goal(routing.Location(pos, orient, surface))) obj_pos = self._privacy.central_object.position for offset in self._privacy.additional_exit_offsets: goals.append( routing.Goal( routing.Location(obj_pos + Vector3(offset.x, 0, offset.y), orient, surface))) if not goals: return Nowhere( 'BuildAndForceSatisfyShooConstraintInteraction, Could not generate goals to exit a privacy region, Sim: {} Privacy Region: {}', sim, self._privacy.constraint.geometry.polygon) yield route = routing.Route(sim.routing_location, goals, routing_context=sim.routing_context) plan_primitive = PlanRoute(route, sim, reserve_final_location=False, interaction=self) yield from element_utils.run_child(timeline, plan_primitive) max_distance = self._privacy._max_line_of_sight_radius * self._privacy._max_line_of_sight_radius * 4 nodes = [] path = plan_primitive.path while path is not None: nodes.extend(path.nodes) path = path.next_path if nodes: previous_node = nodes[0] for node in nodes: node_vector = sims4.math.Vector3(node.position[0], node.position[1], node.position[2]) if not sims4.geometry.test_point_in_compound_polygon( node_vector, self._privacy.constraint.geometry.polygon): position = node_vector if node.portal_id != 0: continue circle_constraint = interactions.constraints.Circle( position, self.TRIVIAL_SHOO_RADIUS, node.routing_surface_id) if circle_constraint.intersect( self._privacy.constraint).valid: continue break previous_node = node position2 = sims4.math.Vector3(previous_node.position[0], previous_node.position[1], previous_node.position[2]) if (position - position2).magnitude_2d_squared() > max_distance: position = self._find_close_position(position, position2) elif (position - sim.position).magnitude_2d_squared() > max_distance: position = self._find_close_position(position, sim.position) p1 = position p2 = self._privacy.central_object.position forward = sims4.math.vector_normalize(p1 - p2) radius_min = 0 radius_max = self._privacy.shoo_constraint_radius angle = sims4.math.PI (cone_geometry, cost_functions) = build_weighted_cone(position, forward, radius_min, radius_max, angle, ideal_radius_min=0, ideal_radius_max=0, ideal_angle=1) subtracted_cone_polygon_list = [] for cone_polygon in cone_geometry.polygon: for privacy_polygon in self._privacy.constraint.geometry.polygon: subtracted_cone_polygons = cone_polygon.subtract( privacy_polygon) if subtracted_cone_polygons: subtracted_cone_polygon_list.extend( subtracted_cone_polygons) compound_subtracted_cone_polygon = sims4.geometry.CompoundPolygon( subtracted_cone_polygon_list) subtracted_cone_geometry = sims4.geometry.RestrictedPolygon( compound_subtracted_cone_polygon, []) subtracted_cone_constraint = Constraint( geometry=subtracted_cone_geometry, scoring_functions=cost_functions, routing_surface=routing_surface, debug_name='ShooedSimsCone', multi_surface=True, los_reference_point=position) point_cost = 5 point_constraint = interactions.constraints.Position( position, routing_surface=routing_surface, multi_surface=True) point_constraint = point_constraint.generate_constraint_with_cost( point_cost) constraints = (subtracted_cone_constraint, point_constraint) return interactions.constraints.create_constraint_set( constraints, debug_name='ShooPositions') yield
def _create_constraint_set(self, sim, timeline): orient = sims4.math.Quaternion.IDENTITY() positions = services.current_zone().lot.corners position = positions[0] goals = [] for pos in positions: while not sims4.geometry.test_point_in_compound_polygon( pos, self._privacy.constraint.geometry.polygon): goals.append( routing.Goal( routing.Location(pos, orient, sim.routing_surface))) if not goals: return Nowhere() route = routing.Route(sim.routing_location, goals, routing_context=sim.routing_context) plan_primitive = PlanRoute(route, sim, reserve_final_location=False) yield element_utils.run_child(timeline, plan_primitive) max_distance = self._privacy._max_line_of_sight_radius * self._privacy._max_line_of_sight_radius * 4 nodes = plan_primitive.path.nodes if nodes: previous_node = nodes[0] for node in nodes: node_vector = sims4.math.Vector3(node.position[0], node.position[1], node.position[2]) if not sims4.geometry.test_point_in_compound_polygon( node_vector, self._privacy.constraint.geometry.polygon): position = node_vector if node.portal_id != 0: pass circle_constraint = interactions.constraints.Circle( position, self.TRIVIAL_SHOO_RADIUS, node.routing_surface_id) if circle_constraint.intersect( self._privacy.constraint).valid: pass break previous_node = node position2 = sims4.math.Vector3(previous_node.position[0], previous_node.position[1], previous_node.position[2]) if (position - position2).magnitude_2d_squared() > max_distance: position = self._find_close_position(position, position2) elif (position - sim.position).magnitude_2d_squared() > max_distance: position = self._find_close_position(position, sim.position) p1 = position p2 = self._privacy.central_object.position forward = sims4.math.vector_normalize(p1 - p2) radius_min = 0 radius_max = self._privacy._SHOO_CONSTRAINT_RADIUS angle = sims4.math.PI (cone_geometry, scoring_functions) = build_weighted_cone(position, forward, radius_min, radius_max, angle, ideal_radius_min=0, ideal_radius_max=0, ideal_angle=1) subtracted_cone_polygon_list = [] for cone_polygon in cone_geometry.polygon: for privacy_polygon in self._privacy.constraint.geometry.polygon: subtracted_cone_polygons = cone_polygon.subtract( privacy_polygon) while subtracted_cone_polygons: subtracted_cone_polygon_list.extend( subtracted_cone_polygons) compound_subtracted_cone_polygon = sims4.geometry.CompoundPolygon( subtracted_cone_polygon_list) subtracted_cone_geometry = sims4.geometry.RestrictedPolygon( compound_subtracted_cone_polygon, []) subtracted_cone_constraint = Constraint( geometry=subtracted_cone_geometry, scoring_functions=scoring_functions, routing_surface=sim.routing_surface, debug_name='ShooedSimsCone', los_reference_point=position) point_cost = 5 point_constraint = interactions.constraints.Position( position, routing_surface=sim.routing_surface) point_constraint = point_constraint.generate_constraint_with_cost( point_cost) constraints = (subtracted_cone_constraint, point_constraint) return interactions.constraints.create_constraint_set( constraints, debug_name='ShooPositions')