def get_edge_constraint(self, constraint_width=1.0, inward_dir=False, return_constraint_list=False, los_reference_point=DEFAULT, sim=None): constraint_list = [] if inward_dir: constraint_list.append(SWIM_AT_NONE_CONSTRAINT) routing_surface = SurfaceIdentifier(services.current_zone_id(), 0, SurfaceType.SURFACETYPE_POOL) interval = WaterDepthIntervals.SWIM else: constraint_list.append(STAND_AT_NONE_CONSTRAINT) routing_surface = SurfaceIdentifier(services.current_zone_id(), 0, SurfaceType.SURFACETYPE_WORLD) interval = WaterDepthIntervals.WET constraint = OceanStartLocationConstraint.create_simple_constraint( interval, constraint_width, sim, routing_surface=routing_surface, los_reference_point=los_reference_point) if not constraint.valid: constraint = ANYWHERE if return_constraint_list: constraint_list.append(constraint) return constraint_list for other_constraint in constraint_list: constraint = constraint.intersect(other_constraint) return constraint
def add_zone_modifier(zone_modifier: TunableInstanceParam( sims4.resources.Types.ZONE_MODIFIER), target_zone_id: int = None, _connection=None): if target_zone_id is None: target_zone_id = services.current_zone_id() persistence_service = services.get_persistence_service() zone_data = persistence_service.get_zone_proto_buff( services.current_zone_id()) if zone_data is None: return if len(zone_data.lot_traits) == ZONE_MODIFIER_CAP: sims4.commands.output( 'There are already {} lot traits on the lot. Remove one first.'. format(ZONE_MODIFIER_CAP), _connection) return zone_modifier_id = zone_modifier.guid64 if zone_modifier_id in zone_data.lot_traits: sims4.commands.output( '{} is already a trait on the lot.'.format(zone_modifier), _connection) return zone_data.lot_traits.append(zone_modifier_id) services.get_zone_modifier_service( ).check_for_and_apply_new_zone_modifiers(target_zone_id)
def __init__(self, obj, routing_surface, orientation, *args, **kwargs): translation = self.get_translation(obj) self._tuned_orientation = orientation orientation = self.get_orientation(obj) if routing_surface == ROUTING_SURFACE_TERRAIN: routing_surface = obj.routing_surface elif routing_surface == ROUTING_SURFACE_OBJECT: routing_surface = obj.provided_routing_surface elif routing_surface == ROUTING_SURFACE_GLOBAL_OBJECT: routing_surface = SurfaceIdentifier( services.current_zone_id(), obj.routing_surface.secondary_id, SurfaceType.SURFACETYPE_OBJECT) elif routing_surface == ROUTING_SURFACE_OCEAN: routing_surface = SurfaceIdentifier(services.current_zone_id(), 0, SurfaceType.SURFACETYPE_POOL) override_level = kwargs.get('override_level') if override_level is not None: routing_surface = SurfaceIdentifier(routing_surface.primary_id, override_level, routing_surface.type) terrain_object = services.terrain_service.terrain_object() translation.y = terrain_object.get_routing_surface_height_at( translation.x, translation.z, routing_surface) super().__init__(translation, orientation=orientation, routing_surface=routing_surface)
def validate_household_sim(test_sim): if test_sim in self._ss3_requests or test_sim in self.special_case_sims: return True if test_sim.is_selectable: run_affordance = self.species_interaction_speed_requirements.species_affordance_mapping.get( test_sim.species) if run_affordance is not None: self.special_case_sims[test_sim] = run_affordance return True else: roommate_service = services.get_roommate_service() if roommate_service is not None and roommate_service.get_home_zone_id( test_sim.sim_id ) == services.current_zone_id(): run_affordance = roommate_service.get_ss3_affordance( ) if run_affordance is not None: self.special_case_sims[ test_sim] = run_affordance return True else: roommate_service = services.get_roommate_service() if roommate_service is not None and roommate_service.get_home_zone_id( test_sim.sim_id) == services.current_zone_id(): run_affordance = roommate_service.get_ss3_affordance( ) if run_affordance is not None: self.special_case_sims[ test_sim] = run_affordance return True return False
def populate_mannequin_protocol_buffer(mannequin_component): persistence_service = services.get_persistence_service() current_zone_id = services.current_zone_id() sim_info_data_proto = persistence_service.add_mannequin_proto_buff( ) sim_info_data_proto.zone_id = services.current_zone_id() sim_info_data_proto.world_id = persistence_service.get_world_id_from_zone( current_zone_id) mannequin_component.populate_sim_info_data_proto( sim_info_data_proto) mannequin_component._resend_mannequin_data()
def remove_all_zone_modifiers(target_zone_id: int = None, _connection=None): if target_zone_id is None: target_zone_id = services.current_zone_id() persistence_service = services.get_persistence_service() zone_data = persistence_service.get_zone_proto_buff( services.current_zone_id()) if zone_data is None: return traits_to_remove = list(zone_data.lot_traits) for trait in traits_to_remove: zone_data.lot_traits.remove(trait) services.get_zone_modifier_service( ).check_for_and_apply_new_zone_modifiers(target_zone_id)
def get_routing_surface_at_or_below_position(position): for level in range(build_buy.get_highest_level_allowed(), build_buy.get_lowest_level_allowed() - 1, -1): if build_buy.has_floor_at_location(position, level): break return SurfaceIdentifier(services.current_zone_id(), level, SurfaceType.SURFACETYPE_WORLD)
def get_nearest_constraint_start_location(self, species, age, start_position, interval: WaterDepthIntervals): surface_type = None if interval == WaterDepthIntervals.WALK or interval == WaterDepthIntervals.WET or interval == WaterDepthIntervals.WADE: surface_type = SurfaceType.SURFACETYPE_WORLD elif interval == WaterDepthIntervals.SWIM: surface_type = SurfaceType.SURFACETYPE_POOL else: logger.error('Unhandled water depth interval {}'.format(interval)) surface_id = SurfaceIdentifier(services.current_zone_id(), 0, surface_type) if interval == WaterDepthIntervals.WALK: interval = WaterDepthIntervals.WADE key = (species, age, interval) if key not in self._constraint_starts: return else: starts = self._constraint_starts[key] if starts: best_start = starts[0] best_distSq = (start_position - best_start.translation).magnitude_squared() for start in starts[1:]: distSq = (start_position - start.translation).magnitude_squared() if distSq < best_distSq: best_start = start best_distSq = distSq return Location(best_start, surface_id)
def c_api_client_connect(session_id, account_id, household_id, persona_name, zone_id, callback, active_sim_id, locale='none', edit_lot_mode=False): account = services.account_service().get_account_by_id( account_id, try_load_account=True) if account is None: account = server.account.Account(account_id, persona_name) account.locale = locale TelemetryTuning.filter_tunable_hooks() zone = services.current_zone() client = zone.client_manager.create_client(session_id, account, household_id) zone.on_client_connect(client) services.on_client_connect(client) yield_zone_id(services.current_zone_id()) if client.household_id == SYSTEM_HOUSEHOLD_ID: zone.game_clock.restore_saved_clock_speed() return NO_HOUSEHOLD_ERROR_CODE status.info('Client {:#08x} ({}) connected to zone {:#08x}'.format( session_id, persona_name, zone_id)) if edit_lot_mode: result = zone.do_build_mode_zone_spin_up(household_id) else: result = zone.do_zone_spin_up(household_id, active_sim_id) if not result: return EXCEPTION_ERROR_CODE return SUCCESS_CODE
def resume(self): if not self.should_resume(): return if services.current_zone_id() == self._zone_id: self._resume_venue_behavior() self._duration_alarm_handle = self.schedule_duration_alarm( self._on_venue_event_complete)
def _replace_object(self, resolver): original_obj = resolver.get_participant(self.participant) if original_obj is None or original_obj.is_sim: return new_obj_def = build_buy.get_replacement_object( services.current_zone_id(), original_obj.id, self.number_replacement_attempts, self.margin_of_error, tags=self.tags, exclude_tags=self.exclude_tags) if new_obj_def is not None: new_obj = objects.system.create_object(new_obj_def) if new_obj is not None: household_owner_id = original_obj.household_owner_id parent_slot = original_obj.parent_slot new_obj.move_to(routing_surface=original_obj.routing_surface, translation=original_obj.position, orientation=original_obj.orientation) new_obj.set_household_owner_id(household_owner_id) if parent_slot is not None: original_obj.set_parent(None) parent_slot.add_child(new_obj) delete_liability = DeleteObjectLiability([original_obj]) self.interaction.add_liability(DELETE_OBJECT_LIABILITY, delete_liability) else: logger.warn( 'Sim Ray could not create an object from the returned definition: {}.', new_obj_def, owner='jwilkinson') else: logger.warn( 'Sim Ray server call did not return a replacement object definition. Try adjusting the tuning to use a larger margin of error.', owner='jwilkinson')
def set_restriction(self, sim_info, game_objects, preference_tag, should_force): zone_preference_data = self._zone_object_preference_datas[( services.current_zone_id(), preference_tag)] if not should_force and sim_info.sim_id in zone_preference_data: return object_id = None subroot_index = None for game_object in game_objects: object_id = game_object.id if game_object.is_part and game_object.restrict_autonomy_preference: subroot_index = game_object.subroot_index else: subroot_index = None if zone_preference_data.get_restricted_sim( object_id, subroot_index) is not None: continue break else: if not should_force: return if object_id is not None: old_sim_id = zone_preference_data.set_restriction( object_id, subroot_index, sim_info.sim_id) if old_sim_id is not None: roommate_service = services.get_roommate_service() if roommate_service is not None: roommate_service.assign_bed(old_sim_id) game_object.update_object_tooltip()
def get_hangout_zone_id(self, prefer_current=False): if self.hangout_setting == ClubHangoutSetting.HANGOUT_NONE: return 0 if self.hangout_setting == ClubHangoutSetting.HANGOUT_VENUE: current_region = services.current_region() def is_valid_zone_id(zone_id): if not self.is_zone_valid_for_gathering(zone_id): return False zone_region = get_region_instance_from_zone_id(zone_id) if zone_region is None: return False elif not current_region.is_region_compatible(zone_region): return False return True venue_service = services.venue_service() available_zone_ids = tuple( filter( is_valid_zone_id, venue_service.get_zones_for_venue_type_gen( self.hangout_venue))) for venue in self.hangout_venue.included_venues_for_club_gathering: included_zone_ids = tuple( filter(is_valid_zone_id, venue_service.get_zones_for_venue_type_gen(venue))) available_zone_ids += included_zone_ids if not available_zone_ids: return 0 if prefer_current: current_zone_id = services.current_zone_id() if current_zone_id in available_zone_ids: return current_zone_id return random.choice(available_zone_ids) return self.hangout_zone_id
def get_waypoint_constraints_gen(self, routing_agent, waypoint_count): zone_id = services.current_zone_id() object_constraints = defaultdict(list) if self.object_tag_generator is not None: object_tag_generator = self.object_tag_generator(WaypointContext(self._sim), None) for constraint in itertools.chain((object_tag_generator.get_start_constraint(),), object_tag_generator.get_waypoint_constraints_gen(routing_agent, MAX_INT32)): level = constraint.routing_surface.secondary_id block_id = get_block_id(zone_id, constraint.average_position, level) object_constraints[block_id].append(constraint) plex_id = services.get_plex_service().get_active_zone_plex_id() or plex_enums.INVALID_PLEX_ID block_data = get_all_block_polygons(plex_id) polygons = defaultdict(list) if self._routing_surface.secondary_id == 0: polygons[0] = self._get_polygons_for_lot() for (block_id, (polys, level)) in block_data.items(): if level != self._routing_surface.secondary_id: continue polygon = CompoundPolygon([Polygon(list(reversed(p))) for p in polys]) if not polygon.area(): continue polygons[block_id].append((polygon, self._routing_surface)) if not polygons: return False yield final_constraints = self._get_waypoint_constraints_from_polygons(polygons, object_constraints, waypoint_count) final_constraints = self.apply_water_constraint(final_constraints) yield from final_constraints
def _constraint_gen(cls, inst, sim, target, *args, to_zone_id=DEFAULT, **kwargs): yield from super(__class__, inst if inst is not None else cls)._constraint_gen( sim, target, *args, **kwargs) yield services.current_zone().get_spawn_point_ignore_constraint() inst_or_cls = inst if inst is not None else cls home_zone_id = sim.sim_info.vacation_or_home_zone_id if to_zone_id is DEFAULT else to_zone_id if home_zone_id == services.current_zone_id(): if services.get_door_service().has_front_door(): yield inst_or_cls.front_door_constraint.create_constraint(sim) else: yield inst_or_cls.home_spawn_point_constraint.create_constraint( sim, lot_id=services.current_zone().lot.lot_id) yield STAND_CONSTRAINT elif sim.sim_info.is_child_or_older: persistence_service = services.get_persistence_service() zone_data = persistence_service.get_zone_proto_buff(home_zone_id) if zone_data is not None and zone_data.world_id == services.current_zone( ).world_id: home_lot_id = zone_data.lot_id yield inst_or_cls.home_spawn_point_constraint.create_constraint( sim, lot_id=home_lot_id) else: yield inst_or_cls.street_spawn_point_constraint.create_constraint( sim)
def update_preference_if_possible(self, sim_info): object_manager = services.object_manager() use_preferences = sim_info.autonomy_use_preferences sim_id = sim_info.sim_id for preference_tag in self.TAGS_TO_CONVERT: if preference_tag in use_preferences: old_object_id = use_preferences[preference_tag] old_object = object_manager.get(old_object_id) if old_object is not None: del use_preferences[preference_tag] subroot_index = None zone_preference_data = self._zone_object_preference_datas[( services.current_zone_id(), preference_tag)] if sim_id in zone_preference_data: continue for old_object_part in old_object.parts: if old_object_part.restrict_autonomy_preference: subroot_index = old_object_part.subroot_index existing_sim_id = zone_preference_data.get_restricted_sim( old_object_id, subroot_index) if existing_sim_id is None: break else: if subroot_index is not None: pass else: zone_preference_data.set_restriction( old_object_id, subroot_index, sim_id) zone_preference_data.set_restriction( old_object_id, subroot_index, sim_id)
def check_if_should_test(self, resolver): if not self.only_use_result_on_home_zone: return True active_household = services.active_household() if active_household is None: return False return active_household.home_zone_id == services.current_zone_id()
def create_starting_location(position=None, orientation=None, transform=None, routing_surface=None, location=None): starting_routing_location = None if location is None: if routing_surface is None: zone_id = services.current_zone_id() routing_surface = routing.SurfaceIdentifier( zone_id, 0, routing.SurfaceType.SURFACETYPE_WORLD) if transform is None: if position is None: logger.error( 'Trying to create a starting location for a FindGoodLocationContext but position is None. If position is going to remain None then either location or transform need to be passed in instead. -trevor' ) if orientation is None: orientation = sims4.math.angle_to_yaw_quaternion(0.0) starting_routing_location = routing.Location( position, orientation, routing_surface) else: starting_routing_location = routing.Location( transform.translation, transform.orientation, routing_surface) else: starting_routing_location = routing.Location( location.transform.translation, location.transform.orientation, location.routing_surface or location.world_routing_surface) return starting_routing_location
def _run_interaction_gen(self, timeline): household = self._sim_info.household sim_infos_to_bring = services.daycare_service().get_abandoned_toddlers(household, (self._sim_info,)) sim_infos_to_bring.append(self._sim_info) caretaker_zone_ids = set() offlot_pets = set() current_zone_id = services.current_zone_id() for sim_info in household: if sim_info is self._sim_info: continue if sim_info.is_human: if sim_info.is_child_or_older: caretaker_zone_ids.add(sim_info.zone_id) if sim_info.zone_id == current_zone_id: continue if sim_info.zone_id == sim_info.vacation_or_home_zone_id: continue offlot_pets.add(sim_info) else: if sim_info.zone_id == current_zone_id: continue if sim_info.zone_id == sim_info.vacation_or_home_zone_id: continue offlot_pets.add(sim_info) for pet in offlot_pets: if pet.zone_id not in caretaker_zone_ids: sim_infos_to_bring.append(pet) daycare_service = services.daycare_service() if daycare_service.is_sim_info_at_daycare(self._sim_info): daycare_service.remove_sim_info_from_daycare(self._sim_info) services.current_zone().venue_service.active_venue.summon_npcs(tuple(sim_infos_to_bring), NPCSummoningPurpose.BRING_PLAYER_SIM_TO_LOT)
def _apply_altitude(self, v, altitude, routing_surface=None): if altitude is None or altitude is KEEP_ALTITUDE: return v final_surface = routing_surface if routing_surface is not None else self.routing_surface if final_surface: level = final_surface.secondary_id else: level = 0 zone_id = services.current_zone_id() world_surface = routing.SurfaceIdentifier( zone_id, level, routing.SurfaceType.SURFACETYPE_WORLD) water_surface = routing.SurfaceIdentifier( zone_id, level, routing.SurfaceType.SURFACETYPE_POOL) object_surface = routing.SurfaceIdentifier( zone_id, level, routing.SurfaceType.SURFACETYPE_OBJECT) world_height = get_terrain_height(v.x, v.z, routing_surface=world_surface) water_height = get_terrain_height(v.x, v.z, routing_surface=water_surface) object_height = get_terrain_height(v.x, v.z, routing_surface=object_surface) h = max(world_height, water_height, object_height) if h == routing_constants.INVALID_TERRAIN_HEIGHT: h = get_terrain_center().y return sims4.math.Vector3(v.x, h + altitude, v.z)
def __call__(self, test_targets=None): target_household = None if self.household_to_test.household_source == UtilityTest.ACTIVE_LOT_HOUSEHOLD: target_household = services.owning_household_of_active_lot() elif self.household_to_test.household_source == UtilityTest.ACTIVE_HOUSEHOLD: target_household = services.active_household() elif self.household_to_test.household_source == UtilityTest.PARTICIPANT_HOUSEHOLD: target = next(iter(test_targets), None) if target is not None: if target.is_sim: target_household = target.household else: target_household = services.household_manager().get(target.get_household_owner_id()) if target_household is not None: utilities_manager = services.get_utilities_manager_by_household_id(target_household.id) elif self.household_to_test.household_source == UtilityTest.ACTIVE_LOT_HOUSEHOLD and self.household_to_test.consider_non_household_lot: utilities_manager = services.get_utilities_manager_by_zone_id(services.current_zone_id()) else: return TestResult(False, 'UtilitiesTest: Required to check utility, but there is no household. Check participant tuning.', tooltip=self.tooltip) if utilities_manager is None: return TestResult(False, 'UtilitiesTest: Required to check utility, but utilities manager is None. Check participant tuning.', tooltip=self.tooltip) for utility_state in self.utility_states: if utilities_manager.is_utility_active(utility_state.utility) != utility_state.require_active: return TestResult(False, 'UtilitiesTest: Utility status for the {} is not correct.', utility_state.utility, tooltip=self.tooltip) return TestResult.TRUE
def decorate_neighborhood_for_holiday(self, holiday_id, decorate_immediately=False, preset_override=None): neighborhood_decoration_state = self.get_neighborhood_state_for_zone( services.current_zone_id()) if neighborhood_decoration_state is None: return holiday_provider = self._get_decoration_provider(holiday_id) for lot in neighborhood_decoration_state.lots: if lot.is_owned_by_active_household(): continue resolver = SingleSimResolver(None, additional_participants={ ParticipantType.PickedZoneId: (lot.zone_id, ) }) if any(resolver(test) for test in self.NON_DECORATABLE_TESTS): decoration_provider = DEFAULT_DECORATION_PROVIDER else: decoration_provider = holiday_provider lot.switch_to_appropriate_type( decoration_provider, DECORATE_IMMEDIATELY if decorate_immediately else self.AUTO_DECORATION_PARAMS, preset_override=preset_override) self._update_current_lot_statistic() self._world_decorations_set[ neighborhood_decoration_state. world_id] = holiday_provider.decoration_type_id
def _test_zone_id(cls, zone_id): if zone_id is None: return TestResult(False, 'Could not resolve into a valid zone id.') active_household = services.active_household() if zone_id == active_household.home_zone_id: return TestResult( False, "Cannot move sim into the active household's home zone.") if zone_id == services.current_zone_id(): return TestResult(False, 'Cannot move Sim into the active zone.') plex_service = services.get_plex_service() if not plex_service.is_zone_an_apartment( zone_id, consider_penthouse_an_apartment=False): persistence_service = services.get_persistence_service() if persistence_service is None: return TestResult(False, 'Persistence service is not initialized.') zone_data = persistence_service.get_zone_proto_buff(zone_id) if zone_data is None: return TestResult(False, 'Could not resolve zone data.') lot_data = persistence_service.get_lot_data_from_zone_data( zone_data) if lot_data is None: return TestResult(False, 'Could not resolve lot data.') venue_tuning = services.get_instance_manager( sims4.resources.Types.VENUE).get(lot_data.venue_key) if not venue_tuning.is_residential: return TestResult(False, 'Only residential venues are eligible.') return TestResult.TRUE
def _get_affected_household(self): household = services.active_household() if household is None: return elif household.home_zone_id != services.current_zone_id(): return return household
def _close_business(self, play_sound=True): if not self._is_open: return if play_sound: sound = PlaySound(services.get_active_sim(), self.tuning_data.audio_sting_close.instance) sound.start() self._employee_manager.close_business() self.send_daily_profit_and_cost_update() self._send_business_closed_telemetry() if self._owner_household_id is not None: owner_household = services.household_manager().get(self._owner_household_id) owner_household.bucks_tracker.deactivate_all_temporary_perk_timers_of_type(self.tuning_data.bucks) self.modify_funds(-self._employee_manager.final_daily_wages(), from_item_sold=False) self.on_store_closed() services.get_event_manager().process_event(TestEvent.BusinessClosed) self._distribute_business_open_status(False) if self.business_zone_id == services.current_zone_id(): self.tuning_data.lighting_helper_close.execute_lighting_helper(self) zone_director = services.venue_service().get_zone_director() if zone_director is not None: zone_director.refresh_open_street_director_status() else: self.run_off_lot_simulation() self._last_off_lot_update = None self._is_open = False self.show_summary_dialog(is_from_close=True) self._open_time = None
def _test(cls, *args, sim_info=None, **kwargs): if sim_info.zone_id == services.current_zone_id(): return TestResult( False, 'Cannot bring a sim to a zone that is already the current zone.' ) return super()._test(*args, **kwargs)
def _test(cls, *args, sim_info=None, **kwargs): if sim_info.zone_id == 0: return TestResult(False, 'Cannot travel to a zone of 0.') if sim_info.zone_id == services.current_zone_id(): return TestResult( False, 'Cannot switch to zone that is the current zone.') return super()._test(*args, **kwargs)
def get_abandoned_toddlers(self, household, sims_infos_to_ignore=()): caretaker_zone_ids = set() offlot_toddlers = set() abandoned_toddlers = [] current_zone_id = services.current_zone_id() for sim_info in household: if sim_info in sims_infos_to_ignore: continue if not sim_info.is_toddler: if sim_info.can_live_alone: caretaker_zone_ids.add(sim_info.zone_id) if sim_info.zone_id == current_zone_id: continue if sim_info.zone_id == sim_info.household.home_zone_id: continue offlot_toddlers.add(sim_info) else: if sim_info.zone_id == current_zone_id: continue if sim_info.zone_id == sim_info.household.home_zone_id: continue offlot_toddlers.add(sim_info) for toddler in offlot_toddlers: if toddler.zone_id not in caretaker_zone_ids: abandoned_toddlers.append(toddler) return abandoned_toddlers
def create_surface_proxy_from_location(location): position = location.transform.translation zone_id = services.current_zone_id() routing_surface = location.routing_surface level = routing_surface.secondary_id pool_block_id = 0 if build_buy.is_location_pool(position, level): pool_block_id = build_buy.get_block_id(zone_id, position, level - 1) if not pool_block_id: logger.error('Failed ot get pool block id from location: {} ', location) return pool = pool_utils.get_pool_by_block_id(pool_block_id) if pool is None: logger.error( 'Failed to get pool from pool block id {} at location: {}', pool_block_id, location) return return PoolPoint(location, pool) if routing_surface.type == routing.SurfaceType.SURFACETYPE_POOL: if services.terrain_service.ocean_object() is None: logger.error('Ocean does not exist at location: {}', location) return return OceanPoint(location) return TerrainPoint(location)
def is_daycare_service_npc_available(self, sim_info=None, household=None): household = services.active_household() if household is None else household if household.home_zone_id == services.current_zone_id(): nanny_situation = self._get_running_situation_for_service(DaycareTuning.NANNY_SERVICE_NPC) if nanny_situation is not None: if sim_info is None: return True service_sim = nanny_situation.service_sim() if service_sim is not None and service_sim.sim_info is sim_info: return True if DaycareTuning.BUTLER_SERVICE_NPC is not None: butler_situation = self._get_running_situation_for_service(DaycareTuning.BUTLER_SERVICE_NPC) if butler_situation is not None: if butler_situation.is_in_childcare_state: if sim_info is None: return True service_sim = butler_situation.service_sim() if service_sim is not None: if service_sim.sim_info is sim_info: return True elif sim_info is None: all_hired_service_npcs = household.get_all_hired_service_npcs() for service_npc in (DaycareTuning.NANNY_SERVICE_NPC, DaycareTuning.BUTLER_SERVICE_NPC): if service_npc is None: continue if service_npc.guid64 in all_hired_service_npcs: return True return False
def _load_household(self, household_id): household = self.get(household_id) if household is not None: for sim_info in household.sim_info_gen(): zone_id = services.current_zone_id() if sim_info.zone_id != zone_id: householdProto = services.get_persistence_service().get_household_proto_buff(household_id) if householdProto is None: logger.error('unable to find household with household id {}'.household_id) return found_sim = False if householdProto.sims.ids: for sim_id in householdProto.sims.ids: if sim_id == sim_info.sim_id: found_sim = True break if found_sim: sim_proto = services.get_persistence_service().get_sim_proto_buff(sim_id) sim_info.load_sim_info(sim_proto) return household logger.info('Starting to load household id = {0}', household_id) household_proto = services.get_persistence_service().get_household_proto_buff(household_id) if household_proto is None: sims4.log.error('Persistence', 'Household proto could not be found id = {0}', household_id) return household = self._load_household_from_household_proto(household_proto) return household
def _update_walkstyle(self, path, actor, time_offset): walkstyle = self._get_walkstyle(actor, path) age = actor.age gender = actor.gender for n in path.nodes: while n.time >= time_offset: self._apply_rules_to_node(n, walkstyle, actor) path.nodes.update_timing(walkstyle, age, gender, time_offset, services.current_zone_id())
def refresh(self, on_travel_away=False): if not self.is_sim_info_valid_to_run_away_actions(): return current_zone = services.current_zone() if not current_zone.is_zone_running and not current_zone.are_sims_hitting_their_marks: return if self._sim_info.zone_id == services.current_zone_id(): self.stop() self._current_away_action = None else: self.start(on_travel_away=on_travel_away)
def _run_interaction_gen(self, timeline): home_zone_id = self.sim.household.home_zone_id if home_zone_id == services.current_zone_id(): return client = services.client_manager().get_first_client() expect_response = True for next_sim_info in client.selectable_sims: next_sim = next_sim_info.get_sim_instance(allow_hidden_flags=ALL_HIDDEN_REASONS) while next_sim is not self.sim and next_sim is not None: expect_response = False travel_liability = TravelSimLiability(self, self.sim.sim_info, self.to_zone_id, is_attend_career=self.attend_career) if expect_response: travel_liability.travel_player() else: self.add_liability(TRAVEL_SIM_LIABILITY, travel_liability)
def _constraint_gen(cls, inst, sim, target, *args, **kwargs): yield super()._constraint_gen(sim, target, *args, **kwargs) yield services.current_zone().get_spawn_point_ignore_constraint() inst_or_cls = inst if inst is not None else cls home_zone_id = sim.household.home_zone_id if home_zone_id == services.current_zone_id(): active_lot = services.current_zone().lot if active_lot.front_door_id is not None: yield inst_or_cls.front_door_constraint.create_constraint(sim) else: yield inst_or_cls.home_spawn_point_constraint.create_constraint(sim, lot_id=active_lot.lot_id) else: persistence_service = services.get_persistence_service() zone_data = persistence_service.get_zone_proto_buff(home_zone_id) if zone_data.world_id == services.current_zone().world_id: home_lot_id = zone_data.lot_id yield inst_or_cls.home_spawn_point_constraint.create_constraint(sim, lot_id=home_lot_id) else: yield inst_or_cls.street_spawn_point_constraint.create_constraint(sim)
def on_enter(self): super().on_enter() client = services.client_manager().get_first_client() home_zone_id = client.household.home_zone_id if home_zone_id == 0: return _ZoneSpinUpStateResult.DONE zone_manager = services.get_zone_manager() loaded_zones = set() loaded_zones.add(services.current_zone_id()) for sim_info in services.sim_info_manager().values(): if sim_info.is_selectable: if sim_info.zone_id not in loaded_zones: zone_manager.load_uninstantiated_zone_data( sim_info.zone_id) loaded_zones.add(sim_info.zone_id) sim_info.away_action_tracker.start() else: sim_info.away_action_tracker.stop() home_zone_id = client.household.home_zone_id if home_zone_id not in loaded_zones: zone_manager.load_uninstantiated_zone_data(home_zone_id) return _ZoneSpinUpStateResult.DONE
def _finalize_death(self): if self._has_finalized_death: return self._has_finalized_death = True sim_info = self.sim.sim_info current_household = sim_info.household death_object = self._death_object_data[0] if death_object is not None: death_object.add_dynamic_component(types.STORED_SIM_INFO_COMPONENT.instance_attr, sim_id=sim_info.id) death_object.update_object_tooltip() death_object.set_household_owner_id(sim_info.household.id) if self._death_object_data[1]: build_buy.move_object_to_household_inventory(death_object) death_tracker = sim_info.death_tracker death_tracker.set_death_type(self.death_type) if self._client is not None: self._client.set_next_sim_or_none(only_if_this_active_sim_info=sim_info) self._client.selectable_sims.remove_selectable_sim_info(sim_info) if not any(sim.is_teen_or_older for sim in self._client.selectable_sims): self._show_death_dialog() persistence_service = services.get_persistence_service() sim_info_manager = services.sim_info_manager() for selectable_sim_info in self._client.selectable_sims: sim_id = selectable_sim_info.id sim_to_destroy = selectable_sim_info.get_sim_instance(allow_hidden_flags=ALL_HIDDEN_REASONS) if sim_to_destroy is not None: sim_to_destroy.destroy(source=sim_to_destroy, cause='Last adult sim dieing, destroying dependent sims.') persistence_service.del_sim_proto_buff(sim_id) sim_info_manager.remove_permanently(selectable_sim_info) self._client.clear_selectable_sims() zone_id = services.current_zone_id() current_household.clear_household_lot_ownership(zone_id) current_household.hidden = True fire_service = services.get_fire_service() if fire_service is not None: fire_service.kill()
def get_work_affordance(self): if self._sim_info.household.home_zone_id == services.current_zone_id(): return self.career_affordance return self.go_home_to_work_affordance
def should_fade_sim_out(self): home_zone_id = self.sim.household.home_zone_id if home_zone_id == services.current_zone_id(): return False return True
def generate_path(self, timeline): start_time = services.time_service().sim_now ticks = 0 try: self.path.status = routing.Path.PLANSTATUS_PLANNING self.path.nodes.clear_route_data() if not self.route.goals: self.path.status = routing.Path.PLANSTATUS_FAILED else: for goal in self.route.goals: self.path.add_goal(goal) for origin in self.route.origins: self.path.add_start(origin) self.sim.on_plan_path(self.route.goals, True) if self.path.nodes.make_path() is True: def is_planning_done(): nonlocal ticks ticks += 1 return not self.path.nodes.plan_in_progress yield element_utils.run_child(timeline, elements.BusyWaitElement(soft_sleep_forever(), is_planning_done)) self.path.nodes.finalize(self._is_failure_route) else: self.path.status = routing.Path.PLANSTATUS_FAILED new_route = routing.Route(self.route.origin, self.route.goals, additional_origins=self.route.origins, routing_context=self.route.context) new_route.path.copy(self.route.path) new_path = routing.Path(self.path.sim, new_route) new_path.status = self.path.status new_path._start_ids = self.path._start_ids new_path._goal_ids = self.path._goal_ids result_path = new_path if len(new_path.nodes) > 0: start_index = 0 current_index = 0 for n in self.path.nodes: if n.portal_object_id != 0: portal_object = services.object_manager(services.current_zone_id()).get(n.portal_object_id) if portal_object is not None and portal_object.split_path_on_portal(): new_path.nodes.clip_nodes(start_index, current_index) new_route = routing.Route(self.route.origin, self.route.goals, additional_origins=self.route.origins, routing_context=self.route.context) new_route.path.copy(self.route.path) next_path = routing.Path(self.path.sim, new_route) next_path.status = self.path.status next_path._start_ids = self.path._start_ids next_path._goal_ids = self.path._goal_ids new_path.next_path = next_path new_path.portal = portal_object new_path = next_path start_index = current_index + 1 current_index = current_index + 1 new_path.nodes.clip_nodes(start_index, current_index - 1) self.route = result_path.route self.path = result_path self.sim.on_plan_path(self.route.goals, False) except Exception: logger.exception('Exception in generate_path') self.path.status = routing.Path.PLANSTATUS_FAILED self.sim.on_plan_path(self.route.goals, False) if self.path.status == routing.Path.PLANSTATUS_PLANNING: self.path.set_status(routing.Path.PLANSTATUS_READY) else: self.path.set_status(routing.Path.PLANSTATUS_FAILED) if gsi_handlers.routing_handlers.archiver.enabled: gsi_handlers.routing_handlers.archive_plan(self.sim, self.path, ticks, (services.time_service().sim_now - start_time).in_real_world_seconds())
def _apply_walkstyle(self, path, actor): walkstyle = self._get_walkstyle(actor, path) origin_q = (float(actor.orientation.x), float(actor.orientation.y), float(actor.orientation.z), float(actor.orientation.w)) origin_t = (float(actor.position.x), float(actor.position.y), float(actor.position.z)) age = actor.age gender = actor.gender if actor.allow_running_for_long_distance_routes: self._running_nodes = self._determine_running_nodes(path) else: self._running_nodes = [] for n in path.nodes: self._apply_rules_to_node(n, walkstyle, actor) current_ticks = int(services.time_service().sim_now) path.nodes.apply_initial_timing(origin_q, origin_t, walkstyle, age, gender, current_ticks, services.current_zone_id())
def _test(cls, *args, sim_info=None, **kwargs): if sim_info.zone_id == 0: return TestResult(False, 'Cannot travel to a zone of 0.') if sim_info.zone_id == services.current_zone_id(): return TestResult(False, 'Cannot switch to zone that is the current zone.') return super()._test(*args, **kwargs)
def _test(cls, *args, sim_info=None, **kwargs): if sim_info.zone_id == services.current_zone_id(): return TestResult(False, 'Cannot bring a sim to a zone that is already the current zone.') return super()._test(*args, **kwargs)