def _get_duration_for_cycle(self, clip, walkstyle_info_dict): builder_name = hash_util.hash32(clip) if builder_name not in walkstyle_info_dict: logger.error( "Can't find the ladder clip {} in the walkstyle info.", clip) return 0 return walkstyle_info_dict[builder_name][self.walkstyle_duration]
def to_slot_hash(slot_name_or_hash): if slot_name_or_hash is None: return 0 if isinstance(slot_name_or_hash, int): return slot_name_or_hash else: return hash_util.hash32(slot_name_or_hash)
def _add_fish_effect(self, fish): if None in self._fish_vfx_handles: index = self._fish_vfx_handles.index(None) else: index = len(self._fish_vfx_handles) self._fish_vfx_handles.append(None) vfx_data = fish.inventory_to_fish_vfx.get( self.inventory_component.inventory_type, None) if vfx_data is not None: vfx_index = index + 1 if self.fish_vfx_prefix is not None: vfx_name = '{}_{}_{}'.format(self.fish_vfx_prefix, vfx_data.vfx_name, vfx_index) else: vfx_name = '{}_{}'.format(vfx_data.vfx_name, vfx_index) vfx_slot_name = '{}{}'.format(vfx_data.vfx_base_bone_name, vfx_index) else: vfx_name = fish.fishbowl_vfx vfx_slot_name = self.VFX_SLOT_NAME vfx_slot = hash_util.hash32(vfx_slot_name) play_effect_handle = vfx.PlayEffect(self, vfx_name, joint_name=vfx_slot) play_effect_handle.start() self._fish_vfx_handles[index] = (fish.id, play_effect_handle)
def _find_slot_name(self, slot_type, check_occupied=False): slot_name = slot_type._bone_name + self.part_suffix if check_occupied: slot_hash = hash32(slot_name) for child in self.children: while child.location.joint_name_hash == slot_hash: return return slot_name
def get_joint_transform_for_joint(self, joint_name): if isinstance(joint_name, str): joint_name = joint_name + str(self.subroot_index) else: joint_name = hash32(str(self.subroot_index), initial_hash=joint_name) transform = get_joint_transform_from_rig(self.rig, joint_name) transform = Transform.concatenate(transform, self.part_owner.transform) return transform
def get_bone_name_hashes_for_part_suffix(cls, part_suffix): if cls._bone_name_hashes_for_part_suffices is None: cls._bone_name_hashes_for_part_suffices = {} if part_suffix in cls._bone_name_hashes_for_part_suffices: return cls._bone_name_hashes_for_part_suffices[part_suffix] bone_names = cls.get_bone_names_for_part_suffix(part_suffix) bone_name_hashes = frozenset(hash32(bone_name) for bone_name in bone_names) cls._bone_name_hashes_for_part_suffices[part_suffix] = bone_name_hashes return bone_name_hashes
def get_bone_name_hashes_for_part_suffix(cls, part_suffix): if cls._bone_name_hashes_for_part_suffices is None: cls._bone_name_hashes_for_part_suffices = {} if part_suffix in cls._bone_name_hashes_for_part_suffices: return cls._bone_name_hashes_for_part_suffices[part_suffix] bone_names = cls.get_bone_names_for_part_suffix(part_suffix) bone_name_hashes = frozenset( hash32(bone_name) for bone_name in bone_names) cls._bone_name_hashes_for_part_suffices[part_suffix] = bone_name_hashes return bone_name_hashes
def spawn_objects(self, position): root = sims4.math.Vector3(float(position.x), 0, float(position.z)) zone = services.current_zone() lot = zone.lot if not self.contained_in_lot(lot, root): closest_point = self.find_nearest_point_on_lot(lot, root) if closest_point is None: return False radius = (self.top_right_pos - self.bottom_left_pos).magnitude_2d()/2 root = closest_point + sims4.math.vector_normalize(sims4.math.vector_flatten(lot.center) - closest_point)*(radius + 1) if not self.contained_in_lot(lot, root): sims4.log.warn('Placement', "Placed the lot objects but the entire bounding box isn't inside the lot. This is ok. If you need them to be inside the lot run the interaction again at a diffrent location.") def _generate_vector(offset_x, offset_z): ground_obj = services.terrain_service.terrain_object() ret_vector = sims4.math.Vector3(root.x + offset_x, 0, root.z + offset_z) ret_vector.y = ground_obj.get_height_at(ret_vector.x, ret_vector.z) return ret_vector def _generate_quat(rot): return sims4.math.Quaternion.from_axis_angle(rot, sims4.math.Vector3(0, 1, 0)) for info in self.setup_lot_objects: new_pos = _generate_vector(info.position.x, info.position.y) new_rot = _generate_quat(sims4.math.PI/180*info.angle) new_obj = self._create_object(info.definition, new_pos, new_rot) if new_obj is None: sims4.log.error('SetupLot', 'Unable to create object: {}', info) for state_value in info.init_state_values: new_obj.set_state(state_value.state, state_value) for child_info in info.children: slot_owner = new_obj if child_info.part_index is not None: for obj_part in new_obj.parts: while obj_part.subroot_index == child_info.part_index: slot_owner = obj_part break bone_name_hash = None if child_info.bone_name is not None: bone_name_hash = hash32(child_info.bone_name) slot_type = None if child_info.slot_type is not None: slot_type = child_info.slot_type while True: for runtime_slot in slot_owner.get_runtime_slots_gen(slot_types={slot_type}, bone_name_hash=bone_name_hash): while runtime_slot.is_valid_for_placement(definition=child_info.definition): break sims4.log.error('SetupLot', 'Unable to find slot for child object: {}', child_info) child = self._create_object(child_info.definition) if child is None: sims4.log.error('SetupLot', 'Unable to create child object: {}', child_info) runtime_slot.add_child(child) for state_value in child_info.init_state_values: child.set_state(state_value.state, state_value)
def get_bone_name_hashes_for_part_suffix(cls, part_suffix): if cls._bone_name_hashes_for_part_suffices is None: cls._bone_name_hashes_for_part_suffices = {} if part_suffix in cls._bone_name_hashes_for_part_suffices: return cls._bone_name_hashes_for_part_suffices[part_suffix] bone_name_hashes = set() if cls.subroot is not None: for bone_name_hash in cls.subroot.bone_names: if part_suffix is not None: bone_name_hash = hash32(str(part_suffix), initial_hash=bone_name_hash) bone_name_hashes.add(bone_name_hash) cls._bone_name_hashes_for_part_suffices[part_suffix] = frozenset( bone_name_hashes) return cls._bone_name_hashes_for_part_suffices[part_suffix]
def to_slot_hash(slot_name_or_hash): if slot_name_or_hash is None: return 0 if isinstance(slot_name_or_hash, int): return slot_name_or_hash return hash_util.hash32(slot_name_or_hash)
def spawn_objects(self, position): root = sims4.math.Vector3(position.x, position.y, position.z) zone = services.current_zone() lot = zone.lot owner_id = lot.owner_household_id if not self.contained_in_lot(lot, root): closest_point = self.find_nearest_point_on_lot(lot, root) if closest_point is None: return False radius = (self.top_right_pos - self.bottom_left_pos).magnitude_2d() / 2 root = closest_point + sims4.math.vector_normalize( sims4.math.vector_flatten(lot.center) - closest_point) * (radius + 1) if not self.contained_in_lot(lot, root): sims4.log.warn( 'Placement', "Placed the lot objects but the entire bounding box isn't inside the lot. This is ok. If you need them to be inside the lot run the interaction again at a diffrent location." ) def _generate_vector(offset_x, offset_z): ground_obj = services.terrain_service.terrain_object() ret_vector = sims4.math.Vector3(root.x + offset_x, root.y, root.z + offset_z) ret_vector.y = ground_obj.get_height_at(ret_vector.x, ret_vector.z) return ret_vector def _generate_quat(rot): return sims4.math.Quaternion.from_axis_angle( rot, sims4.math.Vector3(0, 1, 0)) for info in self.setup_lot_objects: new_pos = _generate_vector(info.position.x, info.position.y) new_rot = _generate_quat(sims4.math.PI / 180 * info.angle) new_obj = self._create_object(info.definition, new_pos, new_rot, owner_id=owner_id) if new_obj is None: sims4.log.error('SetupLot', 'Unable to create object: {}', info) else: for state_value in info.init_state_values: new_obj.set_state(state_value.state, state_value) for child_info in info.children: slot_owner = new_obj if child_info.part_index is not None: for obj_part in new_obj.parts: if obj_part.subroot_index == child_info.part_index: slot_owner = obj_part break bone_name_hash = None if child_info.bone_name is not None: bone_name_hash = hash32(child_info.bone_name) slot_type = None if child_info.slot_type is not None: slot_type = child_info.slot_type for runtime_slot in slot_owner.get_runtime_slots_gen( slot_types={slot_type}, bone_name_hash=bone_name_hash): if runtime_slot.is_valid_for_placement( definition=child_info.definition): break else: sims4.log.error( 'SetupLot', 'Unable to find slot for child object: {}', child_info) child = self._create_object(child_info.definition, owner_id=owner_id) if child is None: sims4.log.error('SetupLot', 'Unable to create child object: {}', child_info) else: runtime_slot.add_child(child) for state_value in child_info.init_state_values: child.set_state(state_value.state, state_value)
class _PortalTypeDataStairs(_PortalTypeDataBase): STAIR_SHOO_POLYGON_PADDING = Tunable( description= '\n When a sim uses a stair case with a stair landing, any sims who are\n in the way will be shooed. The polygon that determines which sims are\n shooed is based on the portals on that landing, but can be padded using\n this constant.\n ', tunable_type=float, default=0.3) FACTORY_TUNABLES = { 'supports_landing_shoo': Tunable( description= '\n If True, sims standing on a stair landing on the object on which\n this portal exists will be shooed from the path of the stairs if\n another sim attempts to use the stairs. This is to avoid clipping.\n ', tunable_type=bool, default=False) } STAIRS_DOWN_CYCLE = hash_util.hash32('stairs_down_cycle') STAIRS_DOWN_CYCLE_R = hash_util.hash32('stairs_down_cycle_r') STAIRS_UP_CYCLE = hash_util.hash32('stairs_up_cycle') STAIRS_UP_CYCLE_R = hash_util.hash32('stairs_up_cycle_r') SPEED_OVERRIDE = hash_util.hash32('speed_override') @property def portal_type(self): return PortalType.PortalType_Animate def get_stair_count(self, obj): return build_buy.get_stair_count(obj.id) def get_additional_required_portal_flags(self, entry_location, exit_location): if entry_location.routing_surface == exit_location.routing_surface: return PortalFlags.STAIRS_PORTAL_SHORT else: return PortalFlags.STAIRS_PORTAL_LONG return 0 def notify_in_use(self, user, portal_instance, portal_object): if self.supports_landing_shoo: routing_surface = None exit_location = portal_instance.there_exit if exit_location.routing_surface.type == SurfaceType.SURFACETYPE_OBJECT: exit_height = terrain.get_terrain_height( exit_location.position.x, exit_location.position.z, routing_surface=exit_location.routing_surface) routing_surface = exit_location.routing_surface landing_points = [] for (there_start, there_end, back_start, back_end, _) in self.get_portal_locations(portal_object): for portal_location in (there_start, there_end, back_start, back_end): if portal_location.routing_surface.type == SurfaceType.SURFACETYPE_OBJECT: portal_height = terrain.get_terrain_height( portal_location.position.x, portal_location.position.z, routing_surface=portal_location.routing_surface ) if math.isclose(portal_height, exit_height): landing_points.append(portal_location.position) polygon = Polygon(landing_points) polygon = polygon.get_convex_hull() polygon = inflate_polygon( polygon, _PortalTypeDataStairs.STAIR_SHOO_POLYGON_PADDING) UserFootprintHelper.force_move_sims_in_polygon( polygon, routing_surface, exclude=(user, )) def add_portal_data(self, actor, portal_instance, is_mirrored, walkstyle): node_data = routing_protocols.RouteNodeData() obj = portal_instance.obj stair_count = self.get_stair_count(obj) node_data.type = routing_protocols.RouteNodeData.DATA_STAIRS op = routing_protocols.RouteStairsData() op.traversing_up = not is_mirrored op.stair_count = stair_count op.walkstyle = walkstyle op.stairs_per_cycle = 1 node_data.data = op.SerializeToString() node_data.do_stop_transition = True node_data.do_start_transition = True return node_data def get_portal_duration(self, portal_instance, is_mirrored, walkstyle, age, gender, species): walkstyle_info_dict = routing.get_walkstyle_info_full( walkstyle, age, gender, species) obj = portal_instance.obj stair_count = self.get_stair_count(obj) builder_name = self.STAIRS_DOWN_CYCLE if is_mirrored else self.STAIRS_UP_CYCLE if builder_name not in walkstyle_info_dict: builder_name = self.STAIRS_DOWN_CYCLE_R if is_mirrored else self.STAIRS_UP_CYCLE_R if builder_name not in walkstyle_info_dict: speed_override = routing.get_walkstyle_property( walkstyle, age, gender, species, self.SPEED_OVERRIDE) if speed_override is None: logger.error( 'Failed to find stair builder or speed_override for walkstyle {}.', walkstyle) return 0 return speed_override * stair_count info = walkstyle_info_dict[builder_name] duration = info['duration'] * stair_count return duration def get_portal_locations(self, obj): stair_lanes = routing.get_stair_portals(obj.id, obj.zone_id) if not stair_lanes: return () locations = [] for lane in stair_lanes: ((there_start, there_end), (back_start, back_end)) = lane (there_start_position, there_start_routing_surface) = there_start (there_end_position, there_end_routing_surface) = there_end (back_start_position, back_start_routing_surface) = back_start (back_end_position, back_end_routing_surface) = back_end if there_start_routing_surface == there_end_routing_surface: required_flags = PortalFlags.STAIRS_PORTAL_SHORT else: required_flags = PortalFlags.STAIRS_PORTAL_LONG locations.append( (Location(there_start_position, routing_surface=there_start_routing_surface), Location(there_end_position, routing_surface=there_end_routing_surface), Location(back_start_position, routing_surface=back_start_routing_surface), Location(back_end_position, routing_surface=back_end_routing_surface), required_flags)) return locations
class TerrainTag(enum.Int): INVALID = 0 BRICK = hash_util.hash32('brick') CARPET = hash_util.hash32('carpet') CEMENT = hash_util.hash32('cement') DIRT = hash_util.hash32('dirt') GRASS = hash_util.hash32('grass') GRAVEL = hash_util.hash32('gravel') HARDWOOD = hash_util.hash32('hardwood') LEAVES = hash_util.hash32('leaves') LINOLEUM = hash_util.hash32('linoleum') MARBLE = hash_util.hash32('marble') METAL = hash_util.hash32('metal') PUDDLE = hash_util.hash32('puddle') SAND = hash_util.hash32('sand') SNOW = hash_util.hash32('snow') STONE = hash_util.hash32('stone') WOOD_DECK = hash_util.hash32('wood deck')
def _tuning_loaded_callback(cls): cls.slot_type = cls if cls._bone_name: cls.bone_name_hash = hash32(cls._bone_name)