def _update_portal_location(self, locations, there_entry, there_exit, obj, other_obj, other_obj_angle_restriction): if there_entry.position == there_exit.position: return entry_in_position = there_entry.position + sims4.math.vector_normalize( there_exit.position - there_entry.position) * self.entry_offset entry_out_position = there_entry.position + sims4.math.vector_normalize( there_exit.position - there_entry.position) * self.exit_offset entry_in_position = Vector3(entry_in_position.x, there_entry.position.y, entry_in_position.z) entry_out_position = Vector3(entry_out_position.x, there_entry.position.y, entry_out_position.z) entry_angle = sims4.math.vector3_angle(there_exit.position - entry_in_position) exit_angle = sims4.math.vector3_angle(entry_in_position - there_exit.position) entry_orientation = sims4.math.angle_to_yaw_quaternion(entry_angle) exit_orientation = sims4.math.angle_to_yaw_quaternion(exit_angle) if self.angle_restriction is not None and not self._is_angle_valid( entry_orientation, obj, self.angle_restriction): return if other_obj_angle_restriction is not None and not self._is_angle_valid( exit_orientation, other_obj, other_obj_angle_restriction): return _there_in_entry = Location(entry_in_position, entry_orientation, there_entry.routing_surface) _there_out_entry = Location(entry_out_position, entry_orientation, there_entry.routing_surface) there_exit.transform = Transform(there_exit.position, exit_orientation) locations.append( (_there_in_entry, there_exit, there_exit, _there_out_entry, 0))
def get_location_data_along_segment_gen(self, first_node_index, last_node_index, time_step=0.3): if self.nodes is None: return first_node = self.nodes[first_node_index] last_node = self.nodes[last_node_index] time = first_node.time end_time = last_node.time if time == end_time == 0.0: routing_surface = first_node.routing_surface_id dist = 0.0 while True: while dist < 1.0: pos = sims4.math.vector_interpolate( Vector3(*first_node.position), Vector3(*last_node.position), dist) dist += time_step yield (Transform(pos, Quaternion(*first_node.orientation)), first_node.routing_surface_id, 0.0) else: while time < end_time: (transform, routing_surface) = self.get_location_data_at_time(time) yield (transform, routing_surface, time) time += time_step
def should_deploy_for_path(self, path, routing_surface): if self.deploy_tuning is None or routing_surface.type not in self.allowed_surfaces or path.length( ) <= self.minimum_route_distance: return False total_dist = 0.0 if any(node.portal_object_id for node in path.nodes): if len(path.nodes) > 1: prev_node = path.nodes[0] object_manager = services.object_manager() nodes = list(path.nodes) for next_node in nodes[1:]: node_dist = (Vector3(*next_node.position) - Vector3(*prev_node.position)).magnitude() total_dist += node_dist prev_node = next_node portal_obj_id = next_node.portal_object_id portal_obj = object_manager.get( portal_obj_id) if portal_obj_id else None if portal_obj: if not self.can_transition_through_portal( portal_obj, next_node.portal_id): break if portal_obj_id: break elif portal_obj_id: break else: total_dist = path.length() return total_dist > self.minimum_route_distance
def _build_footprint_polygon(self): bone_transform = self._get_bone_transform() x_offset = self._scale*self._columns/2 z_offset = self._scale*self._rows/2 v0 = bone_transform.transform_point(Vector3(x_offset, 0, z_offset)) v1 = bone_transform.transform_point(Vector3(-x_offset, 0, z_offset)) v2 = bone_transform.transform_point(Vector3(-x_offset, 0, -z_offset)) v3 = bone_transform.transform_point(Vector3(x_offset, 0, -z_offset)) self._footprint_polygon = sims4.geometry.Polygon([v0, v1, v2, v3])
def on_finalize_load(self): super().on_finalize_load() portal_component = self.get_component(PORTAL_COMPONENT) if portal_component is None: return locator_manager = services.locator_manager() locators = locator_manager.get( OceanTuning.get_beach_locator_definition().id) initial_transforms = [locator.transform for locator in locators] street_instance = services.current_zone().street if street_instance is not None: for beach_data in street_instance.beaches: beach_forward = Vector3(beach_data.forward.x, 0, beach_data.forward.y) orientation = Quaternion.from_forward_vector(beach_forward) transform = Transform(translation=beach_data.position, orientation=orientation) initial_transforms.append(transform) if not initial_transforms: self._off_lot_portals_created = False return off_lot_portal_ids = [] self._create_all_transforms_and_portals_for_initial_transforms( initial_transforms, store_portal_ids=off_lot_portal_ids) self._off_lot_portals_created = bool(off_lot_portal_ids) self._lot_locator_transforms = self._get_lot_locator_transforms() if self._lot_locator_transforms: self._create_all_transforms_and_portals_for_initial_transforms( self._lot_locator_transforms, lot_transforms=True, prior_lengths=self._lot_constraint_starts_base_lengths, store_portal_ids=self._lot_portals) if self._off_lot_portals_created or self._lot_portals: services.object_manager().add_portal_to_cache(self)
def get_start_constraint(self): if self._start_constraint is not None: return self._start_constraint sim = self._context.sim position = self._target.position if self._target is not None else sim.position relative_offset_vector = Vector3( 0, 0, self.ocean_constraint_distance_past_swim_portal) if self._target is not None and self._target.routing_surface is not None: routing_surface = self._target.routing_surface else: routing_surface = sim.routing_surface if routing_surface.type != routing.SurfaceType.SURFACETYPE_POOL: self._start_constraint = OceanStartLocationConstraint.create_simple_constraint( WaterDepthIntervals.SWIM, self.ocean_constraint_radius, sim, self._target, position, ideal_radius=self.constraint_width, ideal_radius_width=self.constraint_width, relative_offset_vector=relative_offset_vector) else: self._start_constraint = Circle( position, self.ocean_constraint_radius, routing_surface=self._routing_surface) self._master_depth_constraint = WaterDepthIntervalConstraint.create_water_depth_interval_constraint( sim, WaterDepthIntervals.SWIM) self._start_constraint = self._start_constraint.intersect( self._master_depth_constraint) return self._start_constraint
def _do_route_gen(timeline): location = routing.Location(Vector3(x, y, z), routing_surface=obj.routing_surface) goal = routing.Goal(location) routing_context = obj.get_routing_context() route = routing.Route(obj.routing_location, (goal, ), routing_context=routing_context) plan_primitive = PlanRoute(route, obj) result = yield from element_utils.run_child(timeline, plan_primitive) if not result: return result yield nodes = plan_primitive.path.nodes if not (nodes and nodes.plan_success): return False yield else: follow_path_element = FollowPath(obj, plan_primitive.path) result = yield from element_utils.run_child( timeline, follow_path_element) if not result: return result yield return True yield
def vector_from_seq(list_or_tuple): if not list_or_tuple: return length = len(list_or_tuple) if length >= 3: return Vector3(list_or_tuple[0], list_or_tuple[1], list_or_tuple[2]) elif length == 2: return Vector2(list_or_tuple[0], list_or_tuple[1])
def _get_pos_for_index(self, index): row = index % self._rows column = index//self._rows x_offset = self._scale*(column - self._columns/2 + 0.5) z_offset = self._scale*(row - self._rows/2 + 0.5) offset = Vector3(x_offset, 0, z_offset) bone_transform = self._get_bone_transform() return bone_transform.transform_point(offset)
def _do_route_to_constraint_gen(self, waypoints, timeline): if self.is_finishing: return False yield plan_primitives = [] for (i, routing_info) in enumerate(self._routing_infos): routing_agent = routing_info[0] routing_context = routing_info[1] route = routing.Route(routing_agent.routing_location, waypoints[-1], waypoints=waypoints[:-1], routing_context=routing_context) plan_primitive = PlanRoute(route, routing_agent, interaction=self) result = yield from element_utils.run_child(timeline, plan_primitive) if not result: self._show_route_fail_balloon() return False yield if not (plan_primitive.path.nodes and plan_primitive.path.nodes.plan_success): self._show_route_fail_balloon() return False yield plan_primitive.path.blended_orientation = self.waypoint_randomize_orientation plan_primitives.append(plan_primitive) if i == len(self._routing_infos) - 1: continue for node in plan_primitive.path.nodes: position = Vector3(*node.position) for goal in itertools.chain.from_iterable(waypoints): if goal.routing_surface_id != node.routing_surface_id: continue dist_sq = (Vector3(*goal.position) - position).magnitude_2d_squared() if dist_sq < self._goal_size: goal.cost = routing.get_default_obstacle_cost() route_primitives = [] track_override = None mask_override = None if self.waypoint_clear_locomotion_mask: mask_override = 0 track_override = 9999 for plan_primitive in plan_primitives: sequence = get_route_element_for_path(plan_primitive.sim, plan_primitive.path, interaction=self, force_follow_path=True, track_override=track_override, mask_override=mask_override) walkstyle_request = self.waypoint_walk_style(plan_primitive.sim) sequence = walkstyle_request(sequence=sequence) route_primitives.append(sequence) result = yield from element_utils.run_child(timeline, do_all(*route_primitives)) return result yield
def __call__(self, obj, posture, routing_surface_start, routing_surface_end, species_overrides): species_portals = [] posture_species = posture.get_animation_species() for species in species_overrides: if species == SpeciesExtended.INVALID: continue if SpeciesExtended.get_species(species) not in posture_species: continue location_entry = self.location_entry(obj).position location_exit = self.location_exit(obj).position back_entry = None back_exit = None if self.bidirectional: exit_x_offset = Vector3(location_entry.x - location_exit.x, 0, 0) location_exit = location_exit + exit_x_offset there_angle = sims4.math.vector3_angle(location_exit - location_entry) there_orientation = sims4.math.angle_to_yaw_quaternion( there_angle) there_entry = Location(location_entry, orientation=there_orientation, routing_surface=routing_surface_start) there_exit = Location(location_exit, orientation=there_orientation, routing_surface=routing_surface_end) back_angle = sims4.math.vector3_angle(location_entry - location_exit) back_orientation = sims4.math.angle_to_yaw_quaternion( back_angle) back_entry_position = location_exit + back_orientation.transform_vector( exit_x_offset) back_entry = Location(back_entry_position, orientation=back_orientation, routing_surface=routing_surface_end) back_exit_position = location_entry + back_orientation.transform_vector( exit_x_offset) back_exit = Location(back_exit_position, orientation=back_orientation, routing_surface=routing_surface_start) else: there_angle = sims4.math.vector3_angle(location_exit - location_entry) there_orientation = sims4.math.angle_to_yaw_quaternion( there_angle) there_entry = Location(location_entry, orientation=there_orientation, routing_surface=routing_surface_start) there_exit = Location(location_exit, orientation=there_orientation, routing_surface=routing_surface_end) species_portals.append( (there_entry, there_exit, back_entry, back_exit, SpeciesExtended.get_portal_flag(species))) return species_portals
def get_footprint_polygon(self, sim_a, sim_b, sim_a_transform, sim_b_transform, routing_surface): reserved_space_a = get_default_reserve_space(sim_a.species, sim_a.age) reserved_space_b = get_default_reserve_space(sim_b.species, sim_b.age) polygon = _generate_poly_points( sim_a_transform.translation, sim_a_transform.orientation.transform_vector(Vector3.Z_AXIS()), sim_b_transform.translation, sim_b_transform.orientation.transform_vector(Vector3.Z_AXIS()), reserved_space_a.left, reserved_space_a.right, reserved_space_a.front, reserved_space_a.back, reserved_space_b.left, reserved_space_b.right, reserved_space_b.front, reserved_space_b.back) return PolygonFootprint( polygon, routing_surface=sim_a.routing_surface, cost=25, footprint_type=FootprintType.FOOTPRINT_TYPE_OBJECT, enabled=True)
def get_initial_offset(self, actor, to_state_name, from_state_name='entry'): arb = NativeArb() self.traverse(from_state_name, to_state_name, arb, from_boundary_conditions=True) offset = arb.get_initial_offset(actor) return Transform(Vector3(*offset[0]), Quaternion(*offset[1]))
def get_location_data_at_time(self, time): if self.nodes is None: return routing_surface = self.node_at_time(time).routing_surface_id translation = Vector3(*self.nodes.position_at_time(time)) translation.y = services.terrain_service.terrain_object( ).get_routing_surface_height_at(translation.x, translation.z, routing_surface) orientation = Quaternion( *self.nodes.orientation_at_time(time, self.blended_orientation)) return (Transform(translation, orientation), routing_surface)
def set_anchor(x: float, y: float, z: float, level: int, opt_sim: OptionalTargetParam = None, _connection=None): sim = get_optional_target(opt_sim, _connection) if sim is None: sims4.commands.output("Couldn't find Sim.", _connection) return vec = Vector3(x, y, z) sim.set_anchor((vec, level))
def get_closest_point_2D(segment, p): a1 = segment[0] a2 = segment[1] (x1, x2) = (a1.x, a2.x) x3 = p.x (z1, z2) = (a1.z, a2.z) z3 = p.z dx = x2 - x1 dz = z2 - z1 t = ((x3 - x1) * dx + (z3 - z1) * dz) / (dx * dx + dz * dz) t = sims4.math.clamp(0, t, 1) x0 = x1 + t * dx z0 = z1 + t * dz return Vector3(x0, p.y, z0)
def _get_offset_positions(self, there_entry, there_exit, angle): if self.bidirectional_portal_offset is not None and there_entry.routing_surface.type == SurfaceType.SURFACETYPE_OBJECT: entry_exit = there_exit.position - there_entry.position unit_vector = sims4.math.vector_normalize(entry_exit) modified_position = Vector3( there_entry.position.x + unit_vector.x * self.bidirectional_portal_offset, there_entry.position.y, there_entry.position.z + unit_vector.z * self.bidirectional_portal_offset) return routing.Location( modified_position, sims4.math.angle_to_yaw_quaternion(angle), routing_surface=there_entry.routing_surface) return there_entry
def _get_slot_pos(self, index): if not index is None: if not 0 <= index <= WorldSpawnPoint.SPAWN_POINT_SLOTS - 1: logger.warn('Slot Index {} for Spawn Point is out of range.', index) return self._center logger.warn('Slot Index {} for Spawn Point is out of range.', index) return self._center offset_from_start = WorldSpawnPoint.SLOT_START_OFFSET_FROM_CENTER offset = Vector3(offset_from_start.x, offset_from_start.y, offset_from_start.z) offset.x += index % WorldSpawnPoint.SPAWN_POINT_SLOT_COLUMNS if index >= WorldSpawnPoint.SPAWN_POINT_SLOT_COLUMNS: offset.z += 1 return self._transform_position(offset)
def get_closest_point_2D(segment, p): a1 = segment[0] a2 = segment[1] x1 = a1.x x2 = a2.x x3 = p.x z1 = a1.z z2 = a2.z z3 = p.z dx = x2 - x1 dz = z2 - z1 t = ((x3 - x1)*dx + (z3 - z1)*dz)/(dx*dx + dz*dz) t = clamp(0, t, 1) x0 = x1 + t*dx z0 = z1 + t*dz return Vector3(x0, p.y, z0)
def _get_carry_system_target(self, callback): (transform, routing_surface) = self._get_best_location(self.carry_target, self.target) transform = Transform(transform.translation, self.sim.orientation) surface_height = services.terrain_service.terrain_object( ).get_routing_surface_height_at(transform.translation.x, transform.translation.z, routing_surface) transform.translation = Vector3(transform.translation.x, surface_height, transform.translation.z) return CarrySystemTerrainTarget(self.sim, self.carry_target, True, transform, routing_surface=routing_surface, custom_event_callback=callback)
def _build_polygon_metadata_dictionary(self, polygon_metadata, constraint, waypoint_index): compound_polygon = constraint.geometry.polygon if isinstance(compound_polygon, CompoundPolygon): for polygon in compound_polygon: if len(polygon) > 0: key = polygon if key not in polygon_metadata: center = sum(polygon, Vector3.ZERO()) / len(polygon) polygon_metadata[key] = (center, []) waypoint_indices = polygon_metadata[key][1] waypoint_indices.append(waypoint_index) else: sim = self._context.sim logger.error( f'Pool Waypoint Generator: Polygon unexpectedly contains no vertices while drawing debug visuals of ${sim}"s route"', owner='jmorrow') else: sim = self._context.sim logger.error( f'Pool Waypoint Generator: Constraint geometry in unexpected format while drawing debug visuals of ${sim}"s route."', owner='jmorrow')
def routing_debug_generate_routing_goals(x: float = None, y: float = None, z: float = None, radius: int = None, obj: OptionalTargetParam = None, _connection=None): if x is None or (y is None or z is None) or radius is None: sims4.commands.output('Please enter 4 floats for x,y,z and radius', _connection) return False obj = get_optional_target(obj, _connection=_connection) if obj is None: return False routing_component = obj.get_component(ROUTING_COMPONENT) if routing_component is None: return False if not postures.posture_graph.enable_debug_goals_visualization: sims4.commands.execute('debugvis.goals.enable', _connection) position = Vector3(x, y, z) routing_surface = routing.SurfaceIdentifier( services.current_zone_id(), 0, routing.SurfaceType.SURFACETYPE_WORLD) constraint = Circle(position, radius, routing_surface) handles = constraint.get_connectivity_handles(obj) handles_str = 'Handles: {}'.format(len(handles)) sims4.commands.output(handles_str, _connection) all_goals = [] for handle in handles: goal_list = handle.get_goals() goals_str = '\tGoals: {}'.format(len(goal_list)) sims4.commands.output(goals_str, _connection) all_goals.extend(goal_list) if postures.posture_graph.enable_debug_goals_visualization: with debugvis.Context('goal_scoring', routing_surface=routing_surface) as layer: for polygon in constraint.geometry.polygon: layer.add_polygon(polygon, routing_surface=routing_surface) for goal in all_goals: position = goal.location.transform.translation layer.add_point(position, routing_surface=routing_surface)
def get_quadtree_polygon(self, position, orientation): length_vector = orientation.transform_vector( Vector3.Z_AXIS()) * self.length / 2 return build_rectangle_from_two_points_and_radius( position + length_vector, position - length_vector, self.width)
def vector_flatten(v): return Vector3(v.x, 0, v.z)
def vector_cross(a, b): return Vector3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x)
import native.animation import sims4.hash_util from singletons import DEFAULT TWO_PI = PI * 2 EPSILON = 1.192092896e-07 QUATERNION_EPSILON = 0.001 MAX_FLOAT = 3.402823466e+38 MAX_UINT64 = 18446744073709551615 MAX_INT64 = 922337203685477580 MAX_UINT32 = 4294967295 MAX_INT32 = 2147483647 MAX_UINT16 = 65535 MAX_INT16 = 32767 POS_INFINITY = float('inf') NEG_INFINITY = float('-inf') FORWARD_AXIS = Vector3.Z_AXIS() UP_AXIS = Vector3.Y_AXIS() def clamp(lower_bound, x, upper_bound): if x < lower_bound: return lower_bound if x > upper_bound: return upper_bound return x def interpolate(a, b, fraction): return a * fraction + (1 - fraction) * b
def get_translation(self, obj): return obj.transform.transform_point( Vector3(self._translation.x, 0, self._translation.y))
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 vector_normalize_2d(v): s = 1/v.magnitude_2d() return Vector3(v.x*s, 0, v.z*s)
import sims4.hash_util import sims4.log TWO_PI = PI*2 EPSILON = 1.192092896e-07 EPSILON_SQ = EPSILON*EPSILON QUATERNION_EPSILON = 0.001 MAX_FLOAT = 3.402823466e+38 MAX_UINT64 = 18446744073709551615 MAX_INT64 = 922337203685477580 MAX_UINT32 = 4294967295 MAX_INT32 = 2147483647 MAX_UINT16 = 65535 MAX_INT16 = 32767 POS_INFINITY = float('inf') NEG_INFINITY = float('-inf') FORWARD_AXIS = Vector3.Z_AXIS() UP_AXIS = Vector3.Y_AXIS() VECTOR3_ZERO = Vector3.ZERO() logger = sims4.log.Logger('Sims4Math') def clamp(lower_bound, x, upper_bound): if x < lower_bound: return lower_bound elif x > upper_bound: return upper_bound return x def interpolate(starting_value, ending_value, fraction): return (1 - fraction)*starting_value + ending_value*fraction def linear_seq_gen(start, stop, step, max_count=None):