def on_update(self): super().on_update() if not services.sim_spawner_service().batch_spawning_complete: return _ZoneSpinUpStateResult.WAITING client = services.client_manager().get_first_client() services.sim_info_manager().on_spawn_sim_for_zone_spin_up_completed( client) services.venue_service().get_zone_director( ).on_spawn_sim_for_zone_spin_up_completed() services.current_zone( ).venue_service.handle_active_lot_changing_edge_cases() services.get_zone_situation_manager( ).on_all_sims_spawned_during_zone_spin_up() club_service = services.get_club_service() if club_service is not None: club_service.on_finish_waiting_for_sim_spawner_service() else: current_zone_id = services.current_zone_id() household = services.active_household() if household.home_zone_id != current_zone_id: sim_info_manager = services.sim_info_manager() traveled_sims = sim_info_manager.get_traveled_to_zone_sim_infos( ) if len(traveled_sims) > 1: services.ensemble_service( ).create_travel_ensemble_if_neccessary(traveled_sims) services.ensemble_service().on_all_sims_spawned_during_zone_spin_up() return _ZoneSpinUpStateResult.DONE
def pre_destroy(self): if not services.get_persistence_service( ).is_save_locked_exclusively_by_holder(self): self._self_destruct() return services.get_persistence_service().unlock_save(self) sim_info = services.sim_info_manager().get(self._host_sim_id) if sim_info is not None: sim_info.degree_tracker.clear_kickout_info() household = sim_info.household if sim_info is not None else None if household is None: self._self_destruct() return active_household = services.active_household() if active_household is None or sim_info not in active_household: self._self_destruct() return self_destruct = True destination_zone_occupied = is_zone_occupied( self._university_housing_destination_zone_id) if len(household) > 1 or destination_zone_occupied: self._show_household_split_dialog(household.id) self_destruct = False else: self._kickout_single_sim() services.venue_service().set_university_housing_kick_out_completed() if self_destruct: self._self_destruct()
def change_venue_type(self, provider, active_venue_type, source_venue_type=None): zone = self.get_zone_for_provider(provider) if zone is None: return False zone_id = zone.id persistence_service = services.get_persistence_service() neighborhood_data = persistence_service.get_neighborhood_proto_buf_from_zone_id( zone_id) for lot_data in neighborhood_data.lots: if zone_id == lot_data.zone_instance_id: if lot_data.venue_key == active_venue_type.guid64: return False lot_data.venue_key = active_venue_type.guid64 for sub_venue_info in lot_data.sub_venue_infos: if sub_venue_info.sub_venue_key == lot_data.venue_key: lot_data.venue_eligible = sub_venue_info.sub_venue_eligible break else: sub_venue_info = lot_data.sub_venue_infos.add() sub_venue_info.sub_venue_key = lot_data.venue_key sub_venue_info.sub_venue_eligible = False lot_data.venue_eligible = False break on_active_lot = zone_id == services.current_zone_id() if on_active_lot: if source_venue_type is None: source_venue_type = VenueService.get_variable_venue_source_venue( active_venue_type) services.venue_service().on_change_venue_type_at_runtime( active_venue_type, source_venue_type) lot_id = None world_id = None if zone.is_instantiated: lot_id = zone.lot.lot_id world_id = zone.world_id else: save_game_data = persistence_service.get_save_game_data_proto() for zone_data in save_game_data.zones: if zone_data.zone_id == zone_id: lot_id = zone_data.lot_id world_id = zone_data.world_id break if lot_id is None or world_id is None: return False distributor = Distributor.instance() venue_update_request_msg = Venue_pb2.VenueUpdateRequest() venue_update_request_msg.venue_key = active_venue_type.guid64 venue_update_request_msg.lot_id = lot_id venue_update_request_msg.world_id = world_id distributor.add_event(Consts_pb2.MSG_SET_SUB_VENUE, venue_update_request_msg) distributor.add_event(Consts_pb2.MSG_NS_NEIGHBORHOOD_UPDATE, neighborhood_data) self.on_venue_type_changed(zone_id, active_venue_type) return True
def stop(self): services.get_event_manager().unregister_single_event( self, TestEvent.SimActiveLotStatusChanged) services.venue_service().on_venue_type_changed.unregister( self._handle_venue_type_changed) self._run_stop_actions() self._clear_action_alarms() if self._scheduler is not None: self._scheduler.destroy()
def change_zone_director(zone_director_tuning: TunableInstanceParam( sims4.resources.Types.ZONE_DIRECTOR), run_cleanup: bool = True, _connection=None): output = sims4.commands.Output(_connection) if zone_director_tuning is None: output('Unknown zone director type') return False new_zone_director = zone_director_tuning() services.venue_service().change_zone_director(new_zone_director, run_cleanup) return True
def buildbuy_session_end(zone_id): services.object_manager( zone_id).rebuild_objects_to_ignore_portal_validation_cache() for obj in services.object_manager(zone_id).get_all(): obj.on_buildbuy_exit() posture_graph_service = services.current_zone().posture_graph_service posture_graph_service.on_exit_buildbuy() _build_buy_exit_callbacks() pythonutils.try_highwater_gc() services.get_zone_modifier_service( ).check_for_and_apply_new_zone_modifiers(zone_id) if _sync_venue_service_to_zone_venue_type(zone_id): zone_director = services.venue_service().get_zone_director() if zone_director is not None: zone_director.on_exit_buildbuy() object_preference_tracker = services.object_preference_tracker() if object_preference_tracker is not None: object_preference_tracker.validate_objects(zone_id) services.business_service().on_build_buy_exit() services.current_zone().on_build_buy_exit() services.utilities_manager().on_build_buy_exit() services.get_reset_and_delete_service().on_build_buy_exit() street_service = services.street_service() if street_service is not None: street = services.current_street() if street is not None: provider = street_service.get_provider(street) if provider is not None: provider.on_build_buy_exit() services.object_manager().clear_objects_to_ignore_portal_validation_cache()
def handle_community_board(community_board_response: str, _connection=None): proto = UI_pb2.CommunityBoardResponse() text_format.Merge(community_board_response, proto) sim_info = services.sim_info_manager().get(proto.sim_id) if sim_info is None: return if proto.provider_type == StreetProvider.provider_type_id: street_civic_policy_service = services.street_service() if street_civic_policy_service is None: sims4.commands.automation_output('Pack not loaded', _connection) sims4.commands.cheat_output('Pack not loaded', _connection) return world_id = sim_info.household.get_home_world_id() street = world.street.get_street_instance_from_world_id(world_id) provider = street_civic_policy_service.get_provider(street) else: source_venue = services.venue_service().source_venue if source_venue is None: return provider = source_venue.civic_policy_provider if provider is not None: for policy in proto.balloted_policies: policy_instance = provider.get_policy_instance_for_tuning( policy.policy_id) if policy_instance is None: continue provider.add_to_ballot(policy_instance) provider.vote_by_instance(policy_instance, policy.count, user_directed=True) provider.modify_influence(sim_info, -proto.influence_points) provider.handle_vote_interaction(sim_info, proto.target_id, bool(proto.balloted_policies))
def cleanup_scheduled_or_active_events(self): drama_scheduler = services.drama_scheduler_service() persistence_service = services.get_persistence_service() for uid in self._organization_festival_events.keys(): drama_scheduler.add_complete_callback( uid, self._reschedule_festival_org_event) cancelled_venue_event_nodes_uids = [] for uid in self._organization_venue_events.keys(): drama_node_inst = drama_scheduler.get_scheduled_node_by_uid(uid) if drama_node_inst is not None: zone_data = persistence_service.get_zone_proto_buff( drama_node_inst.zone_id) if zone_data is None: drama_scheduler.cancel_scheduled_node(uid) cancelled_venue_event_nodes_uids.append(uid) else: venue_tuning = services.venue_service().get_venue_tuning( drama_node_inst.zone_id) if venue_tuning is not self.get_organization_venue_tuning( type(drama_node_inst)): drama_scheduler.cancel_scheduled_node(uid) cancelled_venue_event_nodes_uids.append(uid) else: drama_scheduler.add_complete_callback( uid, self._reschedule_venue_org_event) else: drama_scheduler.add_complete_callback( uid, self._reschedule_venue_org_event) for cancelled_node_uid in cancelled_venue_event_nodes_uids: if cancelled_node_uid in self._organization_venue_events: del self._organization_venue_events[cancelled_node_uid] self.remove_event_update(cancelled_node_uid)
def validate_household_sims(): if services.venue_service().get_university_housing_kick_out_completed( ): return zone = services.current_zone() owner_household = zone.lot.get_household() if not owner_household or owner_household is not services.active_household( ): return situation_manager = services.get_zone_situation_manager() tags = (UniversityHousingTuning. UNIVERSITY_HOUSING_KICKOUT_SITUATION_BLOCKER_TAG, ) if situation_manager.is_situation_with_tags_running(frozenset(tags)): return kickout_payloads = [] UniversityUtils._get_babies_and_parents_to_kickout( owner_household, kickout_payloads) if len(kickout_payloads) == 0: UniversityUtils._get_household_sims_to_kickout( owner_household, kickout_payloads) if len(kickout_payloads) > 0: payload = kickout_payloads[0] create_kick_out_situation( kick_out_reason=payload.kick_out_reason, sim_id=payload.sim_id, additional_sim_ids=payload.additional_sim_ids, university_housing_destination_zone_id=payload. destination_zone_id)
def log_civic_policy_update(zone_director, zone, op): if not archiver.enabled: return venue_service = services.venue_service() (_, _, _, neighborhood_data) = services.current_zone_info() archive_data = { 'zone_director_type': zone_director.instance_name, 'zone_id': zone.id, 'op': op, 'neighborhood': neighborhood_data.name, 'lot_id': zone.lot.lot_id, 'active_venue': type(venue_service.active_venue).__name__, 'source_venue': type(venue_service.source_venue).__name__ } civic_policies = [] provider = venue_service.source_venue.civic_policy_provider if provider: enacted_policies = provider.get_enacted_policies(tuning=True) for policy in provider.get_civic_policies(tuning=True): if policy.vote_count_statistic is None: votes = 'n/a' else: votes = provider.get_stat_value(policy.vote_count_statistic) entry = { 'civic_policy': str(policy), 'enacted': 'X' if policy in enacted_policies else '', 'votes': votes } civic_policies.append(entry) archive_data['lot preparations'] = [] archive_data['spawn objects'] = [] archive_data['civic_policies'] = civic_policies archiver.archive(archive_data)
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 __call__(self): business_manager = services.business_service( ).get_business_manager_for_zone() if business_manager is None: return TestResult(False, 'Not currently on a business lot.') zone_director = services.venue_service().get_zone_director() if zone_director is None: return TestResult(False, 'There is no zone_director for this zone.') from business.business_zone_director_mixin import BusinessZoneDirectorMixin if not isinstance(zone_director, BusinessZoneDirectorMixin): return TestResult( False, 'The current zone director does not implement the BusinessZoneDirectorMixin interface.' ) if zone_director.allows_new_customers(): if not self.customers_allowed: return TestResult( False, 'Business does allow new customers but the test is for not allowing them.' ) elif self.customers_allowed: return TestResult( False, 'Business does not allow new customers and the test is for allowing them.' ) return TestResult.TRUE
def add_employee(self, sim_info, employee_type, is_npc_employee=False): if self.is_employee(sim_info): logger.error( 'Trying to add a duplicate employee: {}. Trying to add as type: {}', sim_info, employee_type) return employee_tuning_data = self.get_employee_tuning_data_for_employee_type( employee_type) employee_career_type = employee_tuning_data.career if employee_career_type is None: logger.error('Trying to add an employee with an invalid type: {}.', employee_type) return employee_career = employee_career_type(sim_info) employee = BusinessEmployeeData(self, sim_info, employee_type) career_location = employee_career.get_career_location() career_location.set_zone_id(self._business_manager.business_zone_id) career_level = self.get_desired_career_level(sim_info, employee_type) + 1 sim_info.career_tracker.add_career(employee_career, user_level_override=career_level) sim_info.add_statistic( employee_tuning_data.satisfaction_commodity, employee_tuning_data.satisfaction_commodity.initial_value) self._employees[sim_info.sim_id] = employee self._register_on_employee_career_removed_callback( sim_info, career=employee_career) if is_npc_employee: return zone_director = services.venue_service().get_zone_director() if zone_director is not None: zone_director.on_add_employee(sim_info, employee)
def on_sim_added_to_skewer(self, sim_info, send_relationship_update=True): if send_relationship_update: sim_info.relationship_tracker.send_relationship_info() is_zone_running = services.current_zone().is_zone_running sim_info.on_sim_added_to_skewer() if not is_zone_running: sim_info.commodity_tracker.start_low_level_simulation() else: services.active_household().distribute_household_data() sim_info.commodity_tracker.send_commodity_progress_update( from_add=True) sim_info.career_tracker.on_sim_added_to_skewer() if sim_info.degree_tracker is not None: sim_info.degree_tracker.on_sim_added_to_skewer() sim_info.send_whim_bucks_update(SetWhimBucks.LOAD) sim_info.resend_trait_ids() sim = sim_info.get_sim_instance(allow_hidden_flags=ALL_HIDDEN_REASONS) if sim is not None: if is_zone_running: sim.inventory_component.visible_storage.allow_ui = True sim.inventory_component.publish_inventory_items() sim.ui_manager.refresh_ui_data() services.autonomy_service().logging_sims.add(sim) sim_info.start_aspiration_tracker_on_instantiation( force_ui_update=True) if sim_info.whim_tracker is not None: sim_info.whim_tracker.start_whims_tracker() zone_director = services.venue_service().get_zone_director() if zone_director is not None: zone_director.on_sim_added_to_skewer(sim_info) sim_info.trait_tracker.sort_and_send_commodity_list()
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 _spawn_fire(self, transform, routing_surface, run_placement_tests=True): if not fire_enabled: logger.info('Trying to spawn fire when fire is disabled. Please use |fire.toggle_enabled cheat to turn fire on.') return if not services.active_lot().is_position_on_lot(transform.translation): logger.info('Trying to spawn fire on a lot other than the active lot.') return if not services.venue_service().venue.allows_fire: logger.info("Trying to spawn a fire on a venue that doesn't allow fire.") return if not (run_placement_tests and self._placement_tests(transform.translation, routing_surface.secondary_id)): logger.info('Trying to spawn a fire on a lot at a position that is not valid.') return fire_object = system.create_object(self.FIRE_OBJECT_DEF) fire_object.move_to(transform=transform, routing_surface=routing_surface) first_fire_on_lot = False if self._fire_objects else True self._fire_objects.add(fire_object) fire_object.add_state_changed_callback(self._fire_object_state_changed_callback) self.start_objects_burning(fire_object) self.add_scorch_mark(fire_object.position, fire_object.location.level) self._derail_routing_sims_if_necessary(fire_object) if first_fire_on_lot: self._start_fire_situations() self.activate_fire_alarms() self.activate_sprinkler_system() self._show_fire_notification() self._create_or_replace_scorch_cleanup_alarm() services.get_persistence_service().lock_save(self) self.register_for_sim_active_lot_status_changed_callback() if self._fire_spread_alarm is None: time_span = date_and_time.create_time_span(minutes=self.FIRE_SPREAD_INTIAL_TIME_IN_SIM_MINUTES) repeating_time_span = date_and_time.create_time_span(minutes=self.FIRE_SPREAD_REPEATING_TIME_IN_SIM_MINUTES) self._fire_spread_alarm = alarms.add_alarm(self, time_span, self._fire_spread_alarm_callback, repeating=True, repeating_time_span=repeating_time_span)
def add_open_street_director(open_street_director_type: TunableInstanceParam( sims4.resources.Types.OPEN_STREET_DIRECTOR), _connection=None): zone_director = services.venue_service().get_zone_director() zone_director.set_open_street_director(open_street_director_type()) sims4.commands.output( 'Open Street Director changed to {}.'.format( zone_director.open_street_director), _connection)
def on_remove(self): self._test_event_unregister(TestEvent.ObjectDestroyed) zone_director = services.venue_service().get_zone_director() remove_situation_bowling_lane = getattr( zone_director, 'remove_situation_bowling_lane', None) if remove_situation_bowling_lane: remove_situation_bowling_lane(self.id) super().on_remove()
def on_career_event_stop(self): self._advance_state(CareerEventState.STOPPED) resolver = SingleSimResolver(self._career.sim_info) for loot in self.loots_on_end: if loot is not None: loot.apply_to_resolver(resolver) curr_zone = services.venue_service().get_zone_director() if curr_zone and self.zone_director and self.zone_director.guid64 == curr_zone.guid64: curr_zone.on_career_event_stop()
def _load_bowling_lane(self): reader = self._seed.custom_init_params_reader if reader is None: return bowling_lane_id = reader.read_uint64(BOWLING_LANE_TOKEN, None) if bowling_lane_id is None: logger.error('Failed to find bowling lane id from {} reader.', self) return self._bowling_lane = services.object_manager().get(bowling_lane_id) if self._bowling_lane is None: logger.error( 'Failed to find bowling lane id {} from object manager.', bowling_lane_id) return self._bowling_lane_chosen = True services.venue_service().get_zone_director( ).set_situation_bowling_lane(self.id, self._bowling_lane)
def request_zone_director(self): if self.zone_director is not None: zone_director = self.zone_director(career_event=self) venue_service = services.venue_service() if venue_service.has_zone_director: venue_service.change_zone_director(zone_director, True) else: preserve_state = self._state >= CareerEventState.RUNNING venue_service.request_zone_director(zone_director, ZoneDirectorRequestType.CAREER_EVENT, preserve_state=preserve_state)
def situation_meets_starting_requirements(cls, total_bowling_lanes=None, **kwargs): if total_bowling_lanes is None: total_bowling_lanes = services.venue_service().get_zone_director( ).get_total_bowling_lanes() if cls.required_bowling_lanes.compare(total_bowling_lanes): return True return False
def venue_civic_policy_vote( policy: TunableInstanceParam(sims4.resources.Types.SNIPPET), count: int = 1, _connection=None): source_venue = services.venue_service().source_venue if source_venue is None or not ( source_venue.civic_policy_provider is None or not source_venue.civic_policy_provider.vote(policy, count)): sims4.commands.cheat_output('Could not add vote to {}'.format(policy), _connection)
def _apply_to_subject_and_target(self, subject, target, resolver): business_manager = services.business_service().get_business_manager_for_zone() if business_manager is None: return zone_director = services.venue_service().get_zone_director() if zone_director is None: return if not isinstance(zone_director, BusinessZoneDirectorMixin): return zone_director.set_customers_allowed(self._allow_customers)
def print_situation_shifts(_connection=None): zone_director = services.venue_service().get_zone_director() if not hasattr(zone_director, 'situation_shifts'): sims4.commands.output('{} has no schedule'.format(zone_director), _connection) return def output(s): sims4.commands.output(s, _connection) for shift in zone_director.situation_shifts: shift.shift_curve.debug_output_schedule(output)
def venue_civic_policy_repeal( policy: TunableInstanceParam(sims4.resources.Types.SNIPPET), _connection=None): source_venue = services.venue_service().source_venue if source_venue is None or not ( source_venue.civic_policy_provider is None or not source_venue.civic_policy_provider.repeal(policy)): sims4.commands.automation_output('{} not repealed'.format(policy), _connection) sims4.commands.cheat_output('{} not repealed'.format(policy), _connection)
def on_enter(self): super().on_enter() venue_service = services.venue_service() venue_service.setup_lot_premade_status() venue_service.make_venue_type_zone_director_request() situation_manager = services.get_zone_situation_manager() situation_manager.create_seeds_during_zone_spin_up() situation_manager.make_situation_seed_zone_director_requests() services.drama_scheduler_service().make_zone_director_requests() venue_service._select_zone_director() venue_service.determine_which_situations_to_load() return _ZoneSpinUpStateResult.DONE
def _on_set_sim_job(self, sim, job): super()._on_set_sim_job(sim, job) if self._bowling_lane is None: self._bowling_lane = services.venue_service().get_zone_director( ).get_situation_bowling_lane(self.id) if self._bowling_lane is None: logger.error( 'Failed to add bowling lane object relationship to Sims because bowling lane is None.' ) return self._bowling_lane_chosen = True ObjectRelationshipComponent.setup_relationship(sim, self._bowling_lane)
def _temple_needs_reset(self): if self._temple_state == self.TEMPLE_STATE_NEEDS_RESET: return True elif self._temple_state == self.TEMPLE_STATE_COMPLETE: sim_info_manager = services.sim_info_manager() temple_zones = tuple(services.venue_service().get_zones_for_venue_type_gen(self.TEMPLE_VENUE_TUNING)) if len(temple_zones) != 1: logger.error('Found either 0 or more than 1 zone that is set as a temple venue. There can be only one!') temple_zone_id = next(iter(temple_zones)) if not any(sim.zone_id == temple_zone_id and sim.is_played_sim for sim in sim_info_manager.get_all()): return True return False
def _end_venue_behavior(self): if self.zone_director is not None: venue_service = services.venue_service() if type(venue_service.get_zone_director()) is self.zone_director: if self.ending_notification is not None: dialog = self.ending_notification( services.active_sim_info()) dialog.show_dialog() venue_service.change_zone_director( venue_service.active_venue.zone_director(), True) elif self.ending_notification is not None: dialog = self.ending_notification(services.active_sim_info()) dialog.show_dialog()
def _get_jungle_open_street_director(): venue_service = services.venue_service() if venue_service is None: return zone_director = venue_service.get_zone_director() if zone_director is None: return open_street_director = zone_director.open_street_director if open_street_director is None: return elif not isinstance(open_street_director, JungleOpenStreetDirector): return return open_street_director