def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._walker = None self._flavor_cooldown_until = services.time_service().sim_now + clock.interval_in_sim_minutes(10) self._social_cooldown_until = services.time_service().sim_now + clock.interval_in_sim_minutes(10) self._other_social_situation = None self._social_interaction = None
def __init__(self, tracker, initial_value): super().__init__(tracker, initial_value) self._decay_enabled = False self._decay_rate_override = UNSET self._callbacks = [] self._suppress_update_active_callbacks = False self._alarm_handle = None self._active_callback = None if self.max_simulate_time_on_load is not None: now = services.time_service().sim_now if services.current_zone().is_zone_loading: world_game_time = services.game_clock_service().zone_init_world_game_time() neg_max_update_time = create_time_span(minutes=-self.max_simulate_time_on_load) diff = world_game_time + neg_max_update_time if diff > now: update_time = diff else: update_time = now self._last_update = update_time else: self._last_update = now else: self._last_update = services.time_service().sim_now self._decay_rate_modifier = 1 self._decay_rate_modifiers = [] self._convergence_value = self._default_convergence_value self._recalculate_modified_decay_rate()
def _setup_object_layer(self, scheduler, alarm_data, extra_data): if self._being_cleaned_up: logger.error('{} trying to setup a layer when being cleaned up', self) return conditional_layer = alarm_data.entry.conditional_layer if conditional_layer is not None: if conditional_layer not in self._current_layers: now = services.time_service().sim_now start_time = now + now.time_till_timespan_of_week( alarm_data.start_time, optional_end_time=alarm_data.end_time) end_time = now + now.time_till_timespan_of_week( alarm_data.end_time) self._create_layer(conditional_layer, start_time, end_time) else: (start_time, end_time, end_handle) = self._current_layers[conditional_layer] now = services.time_service().sim_now if end_time - now < alarm_data.end_time - now: self._update_destruction_alarm(conditional_layer, alarm_data.end_time) else: logger.warn( 'An object layer schedule entry for {} has been tuned with no layer name.', self)
def schedule_reset_asap(self, reset_reason=ResetReason.RESET_EXPECTED, source=None, cause=None): def call_reset(timeline): self.reset(reset_reason, source=source, cause=cause) element = build_element(call_reset) services.time_service().sim_timeline.schedule_asap(element)
def _trigger_idle_animation(self, state, new_value, from_init): if self._component_suppressed: return if new_value in self.idle_animation_map: current_zone = services.current_zone() if current_zone is None or from_init and current_zone.is_zone_loading: return False else: new_animation = self.idle_animation_map[new_value] self._stop_animation_element() self._current_idle_state_value = new_value if new_animation is not None: sequence = () if new_animation.repeat: self._wakeable_element = element_utils.soft_sleep_forever( ) sequence = self._wakeable_element animation_element = new_animation(self.owner, sequence=sequence) self._idle_animation_element = build_element( (animation_element, flush_all_animations)) services.time_service().sim_timeline.schedule( self._idle_animation_element) return True return False
def archive_sim_timeline_context_manager(sim, module, log_message, interaction=None): if not archiver.enabled: yield None else: services_time_service = services.time_service() if services_time_service is not None and services_time_service.sim_timeline is not None: start_time = services_time_service.sim_timeline.now else: start_time = None try: archive_sim_timeline(sim, module, 'Start', log_message, interaction=interaction) yield None finally: duration = None if start_time is not None: services_time_service = services.time_service() if services_time_service is not None and services_time_service.sim_timeline is not None: duration = services_time_service.sim_timeline.now - start_time archive_sim_timeline(sim, module, 'Completed', log_message, interaction=interaction, duration=duration)
def _move_objects(self): objects_to_move = services.object_manager().get_objects_matching_tags(self.object_tags, match_any=True) if not objects_to_move: return resolver = self._get_placement_resolver() choices = [(location.weight.get_multiplier(resolver), location.placement_strategy) for location in self.placement_strategy_locations] chosen_strategy = random.weighted_random_item(choices) do_fade = self.fade is not None out_sequence = [] moves = [] in_sequence = [] for object_to_move in objects_to_move: object_to_move.cancel_interactions_running_on_object(FinishingType.OBJECT_CHANGED, cancel_reason_msg='Object changing location.') if self.vfx_on_move is not None: out_sequence.append(lambda _, object_to_move=object_to_move: self.vfx_on_move(object_to_move).start_one_shot()) if do_fade: out_sequence.append(lambda _, object_to_move=object_to_move: object_to_move.fade_out(self.fade.out_time)) moves.append(lambda _, object_to_move=object_to_move: chosen_strategy.try_place_object(object_to_move, resolver)) if do_fade: in_sequence.append(lambda _, object_to_move=object_to_move: object_to_move.fade_in(self.fade.in_time)) sequence = [] if out_sequence: sequence.append(out_sequence) sequence.append(SoftSleepElement(clock.interval_in_sim_minutes(self.fade.out_time))) sequence.append(moves) if in_sequence: sequence.append(in_sequence) element = build_element(sequence, critical=CleanupType.RunAll) services.time_service().sim_timeline.schedule(element)
def __init__(self, tracker, initial_value): super().__init__(tracker, initial_value) self._decay_enabled = False self._decay_rate_override = UNSET self._callbacks = [] self._suppress_update_active_callbacks = False self._alarm_handle = None self._active_callback = None if self.max_simulate_time_on_load is not None: now = services.time_service().sim_now if services.current_zone().is_zone_loading: world_game_time = services.game_clock_service( ).zone_init_world_game_time() neg_max_update_time = create_time_span( minutes=-self.max_simulate_time_on_load) diff = world_game_time + neg_max_update_time if diff > now: update_time = diff else: update_time = now self._last_update = update_time else: self._last_update = now else: self._last_update = services.time_service().sim_now self._decay_rate_modifier = 1 self._decay_rate_modifiers = [] self._convergence_value = self._default_convergence_value self._recalculate_modified_decay_rate()
def schedule_destroy_asap(self, post_delete_func=None, source=None, cause=None, **kwargs): def call_destroy(timeline): if services.reset_and_delete_service.can_be_destroyed(self): self.destroy(source=source, cause=cause, **kwargs) element = elements.CallbackElement(elements.FunctionElement(call_destroy), complete_callback=post_delete_func, hard_stop_callback=post_delete_func, teardown_callback=None) services.time_service().sim_timeline.schedule_asap(element)
def create_sim_timeline_data(zone_id:int=None): time_service = services.time_service() if time_service is None: return sim_timeline = time_service.sim_timeline if sim_timeline is None: return return _create_timeline_fields(services.time_service().sim_timeline)
def advance_game_time(hours:int=0, minutes:int=0, seconds:int=0, _connection=None): previous_time = services.time_service().sim_now services.game_clock_service().advance_game_time(hours=hours, minutes=minutes, seconds=seconds) new_time = services.time_service().sim_now services.sim_info_manager().auto_satisfy_sim_motives() output = sims4.commands.Output(_connection) output('previous time = {}'.format(previous_time)) output('new time = {}'.format(new_time))
def now(_connection=None): output = sims4.commands.Output(_connection) game_clock_ticks = services.time_service().sim_now.absolute_ticks() server_ticks = services.server_clock_service().ticks() output('Gameclock ticks: {} Server Ticks: {}'.format(game_clock_ticks, server_ticks)) timeline_now = services.time_service().sim_now game_clock_now = services.game_clock_service().now() output('Sim timeline now: {}'.format(timeline_now)) output('Game clock now: {}'.format(game_clock_now))
def _setup_scoring_alarm(self): day_time = date_and_time.create_date_and_time(hours=self.SCORING_TIME) now = services.time_service().sim_now time_delay = now.time_till_next_day_time(day_time) if time_delay.in_ticks() == 0: time_delay = date_and_time.create_time_span(days=1) schedule_time = now + time_delay sim_timeline = services.time_service().sim_timeline self._processor = sim_timeline.schedule(elements.GeneratorElement(self._process_scoring_gen), when=schedule_time)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._walker = None self._flavor_cooldown_until = services.time_service( ).sim_now + clock.interval_in_sim_minutes(10) self._social_cooldown_until = services.time_service( ).sim_now + clock.interval_in_sim_minutes(10) self._other_social_situation = None self._social_interaction = None
def _trigger_idle_animation(self, state, new_value): if new_value in self._idle_animation_map: new_animation = self._idle_animation_map[new_value] self._hard_stop_animation_element() self._current_idle_state_value = new_value if new_animation is not None: animation_element = new_animation(self.owner) self._idle_animation_element = build_element((animation_element, flush_all_animations)) services.time_service().sim_timeline.schedule(self._idle_animation_element) return True return False
def _create_departing_seed_and_travel(self, situation_type, situation_id, guest_list=None, user_facing=True, duration_override=None, custom_init_writer=None, zone_id=0, scoring_enabled=True): traveling_sim = guest_list.get_traveler() if traveling_sim is None: logger.error( 'No traveling sim available for creating departing seed for situation: {}.', situation_type) return if traveling_sim.client is None: logger.error( 'No client on traveling sim: {} for for situation: {}.', traveling_sim, situation_type) return if traveling_sim.household is None: logger.error( 'No household on traveling sim for for situation: {}.', situation_type) return situation_seed = SituationSeed(situation_type, SeedPurpose.TRAVEL, situation_id, guest_list, user_facing, duration_override, zone_id, scoring_enabled=scoring_enabled) if situation_seed is None: logger.error('Failed to create departing seed.for situation: {}.', situation_type) return if custom_init_writer is not None: situation_seed.setup_for_custom_init_params(custom_init_writer) self._departing_situation_seed = situation_seed travel_info = protocolbuffers.InteractionOps_pb2.TravelSimsToZone() travel_info.zone_id = zone_id travel_info.sim_ids.append(traveling_sim.id) traveling_sim_ids = guest_list.get_other_travelers(traveling_sim) travel_info.sim_ids.extend(traveling_sim_ids) distributor.system.Distributor.instance().add_event( protocolbuffers.Consts_pb2.MSG_TRAVEL_SIMS_TO_ZONE, travel_info) services.game_clock_service().request_pause('Situation Travel') logger.debug('Travel seed creation time {}', services.time_service().sim_now) logger.debug('Travel seed future time {}', services.time_service().sim_future) return situation_id
def set_up_decay_handler(self, global_policy, end_time_from_load=None): if global_policy.decay_handler is None: timeline = services.time_service().sim_timeline start_time = services.time_service().sim_now if end_time_from_load: end_time = date_and_time.DateAndTime(end_time_from_load) else: end_time = start_time + date_and_time.create_time_span( days=global_policy.decay_days) global_policy.decay_handler = timeline.schedule( elements.GeneratorElement(global_policy.decay_policy), end_time)
def _update_info_on_number_of_npcs(self, force_update=False): if self._next_npc_count_time > services.time_service().sim_now and not force_update: return self._next_npc_count_time = services.time_service().sim_now + self._npc_count_cooldown self._number_of_instantiated_npcs = 0 self._number_of_leaving_npcs = 0 for sim in services.sim_info_manager().instanced_sims_gen(): if sim.sim_info.is_npc: self._number_of_instantiated_npcs += 1 if self.sim_is_leaving(sim): self._number_of_leaving_npcs += 1 self._on_npc_count_updated()
def _initialize_alarm(self): if not services.time_service(): return current_time = services.time_service().sim_now initial_time_span = current_time.time_till_next_day_time( SicknessTuning.SICKNESS_TIME_OF_DAY) repeating_time_span = date_and_time.create_time_span(days=1) self._alarm_handle = alarms.add_alarm( self, initial_time_span, self._trigger_sickness_distribution_alarm_callback, repeating=True, repeating_time_span=repeating_time_span)
def _set_up_bill_timer(self): day = self.TIME_TO_PLACE_BILL_IN_HIDDEN_INVENTORY.day hour = self.TIME_TO_PLACE_BILL_IN_HIDDEN_INVENTORY.hour minute = self.TIME_TO_PLACE_BILL_IN_HIDDEN_INVENTORY.minute time = create_date_and_time(days=day, hours=hour, minutes=minute) time_until_bill_delivery = services.time_service().sim_now.time_to_week_time(time) bill_delivery_time = services.time_service().sim_now + time_until_bill_delivery end_of_first_week = DateAndTime(0) + interval_in_sim_weeks(1) if bill_delivery_time < end_of_first_week: time_until_bill_delivery += interval_in_sim_weeks(1) if time_until_bill_delivery.in_ticks() <= 0: time_until_bill_delivery = TimeSpan(1) self._bill_timer_handle = alarms.add_alarm(self, time_until_bill_delivery, lambda _: self.allow_bill_delivery())
def on_response(dialog): if not dialog.accepted: return name = dialog.text_input_responses.get(self.TEXT_INPUT_NEW_NAME) description = dialog.text_input_responses.get(self.TEXT_INPUT_NEW_DESCRIPTION) target = self.target if target is not None: if name is not None: target.set_custom_name(name) if description is not None: target.set_custom_description(description) self._update_ui_metadata(target) sequence = self._build_outcome_sequence() services.time_service().sim_timeline.schedule(element_utils.build_element(sequence))
def _SetupZoneHandling () -> None: global _lastUpdateTick, _standardUpdateAlarm timeService = services.time_service() # type: time_service.TimeService _lastUpdateTick = timeService.sim_now.absolute_ticks() simInfoManager = services.sim_info_manager() # type: sim_info_manager.SimInfoManager if simInfoManager is not None: simInfoManager.register_callback(indexed_manager.CallbackTypes.ON_OBJECT_ADD, _OnSimAddCallback) simInfoManager.register_callback(indexed_manager.CallbackTypes.ON_OBJECT_REMOVE, _OnSimRemoveCallback) if services.time_service() is not None: alarmTimeSpan = date_and_time.TimeSpan(_standardUpdateInterval) _standardUpdateAlarm = alarms.add_alarm(sys.modules[__name__], alarmTimeSpan, _StandardUpdateCallback, repeating = True)
def timeline_clear(_connection=None): timeline = services.time_service().sim_timeline for handle in sorted(timeline.heap): while not handle.element is None: if isinstance(handle.element, alarms.AlarmElement): pass timeline.hard_stop(handle)
def execute_interaction(interaction) -> ExecuteResult: if interaction: if interaction.affordance.cheat: with telemetry_helper.begin_hook(sims4.commands.cheats_writer, sims4.commands.TELEMETRY_HOOK_INTERACTION) as hook: hook.write_string(sims4.commands.TELEMETRY_FIELD_NAME, interaction.__str__()) hook.write_string(sims4.commands.TELEMETRY_FIELD_TARGET, str(interaction.target)) if interaction.affordance.immediate: interaction._trigger_interaction_start_event() immediate_timeline = services.time_service().sim_timeline.get_sub_timeline() result_element = elements.ResultElement(elements.GeneratorElement(interaction._run_gen)) immediate_timeline.schedule(result_element) immediate_timeline.simulate(immediate_timeline.now) if immediate_timeline.heap: logger.error('On immediate execute_interaction, immediate timeline is not empty') immediate_timeline.heap.clear() run_result = result_element.result interaction._trigger_interaction_complete_test_event() if run_result: exit_behavior = interaction._exit(None, False) try: next(exit_behavior) logger.error('Running immediate exit_behavior yielded despite allow_yield=False') except StopIteration: pass execute_result = ExecuteResult(run_result, interaction, None) log_interaction('Immediate', interaction, '{}'.format(execute_result)) return execute_result context = interaction.context return ExecuteResult(context.sim.queue.append(interaction), interaction, None) return ExecuteResult(False, None, 'Trying to execute a None interaction.')
def is_player_active(self): if self._get_last_user_directed_action_time() is None: return False delta = services.time_service().sim_now - self._get_last_user_directed_action_time() if delta >= AutonomyMode.get_autonomy_delay_after_user_interaction(): return False return True
def set_last_autonomous_action_time(self, to_reschedule_autonomy=True): now = services.time_service().sim_now logger.debug('Setting last autonomous action time for {} to {}', self.owner, now) self._last_autonomous_action_time = now self._last_autonomy_result_was_none = False if to_reschedule_autonomy: self._schedule_next_full_autonomy_update()
def get_sims_for_job(session_id, sim_id, situation_type, job_type, *job_assignments, _connection=None): sim = get_optional_target(sim_id, _connection) situation_start_time = services.time_service().sim_now duration = situation_type.duration if duration > 0: situation_end_time = situation_start_time + date_and_time.create_time_span(0, 0, duration) else: situation_start_time = date_and_time.INVALID_DATE_AND_TIME situation_end_time = date_and_time.INVALID_DATE_AND_TIME results = services.sim_filter_service().submit_filter(job_type.filter, None, requesting_sim_info=sim.sim_info, start_time=situation_start_time, end_time=situation_end_time, allow_yielding=False) if job_type.additional_filter_for_user_selection: sim_constraints = {result.sim_info.id for result in results} results = services.sim_filter_service().submit_filter(job_type.additional_filter_for_user_selection, None, requesting_sim_info=sim.sim_info, start_time=situation_start_time, end_time=situation_end_time, sim_constraints=sim_constraints, allow_yielding=False) msg = Situations_pb2.SituationJobSims() msg.situation_session_id = session_id msg.job_resource_id = job_type.guid msg.requirements = job_type.requirement_text results.sort(key=lambda x: (x.sim_info.is_npc, x.sim_info.last_name)) for result in results: msg.sim_ids.append(result.sim_info.id) with ProtocolBufferRollback(msg.sims) as situation_job_sim: situation_job_sim.sim_id = result.sim_info.id if result.sim_info.household.id == services.active_household_id(): situation_job_sim.account_id = result.sim_info.account_id while result.conflicting_career_track_id: situation_job_sim.career_track_id = result.conflicting_career_track_id shared_messages.add_message_if_selectable(services.object_manager().get(sim.id), Consts_pb2.MSG_SITUATION_JOB_SIMS, msg, True)
def save(self, persistence_master_message): persistable_data = persistence_protocols.PersistenceMaster.PersistableData() persistable_data.type = persistence_protocols.PersistenceMaster.PersistableData.ObjectAgeComponent obj_age_data = persistable_data.Extensions[persistence_protocols.PersistableObjectAgeComponent.persistable_data] obj_age_data.age = self.get_current_age() obj_age_data.saved_tick = services.time_service().sim_now.absolute_ticks() persistence_master_message.data.extend([persistable_data])
def _schedule_next_alarm(self, schedule_immediate=False, min_duration_remaining=None): now = services.time_service().sim_now (time_span, best_work_data) = self.time_until_next_scheduled_event( now, schedule_immediate=schedule_immediate, min_duration_remaining=min_duration_remaining) if self._min_alarm_time_span is not None and time_span < self._min_alarm_time_span: time_span = self._min_alarm_time_span if time_span == date_and_time.TimeSpan.ZERO and schedule_immediate: time_span = date_and_time.TimeSpan.ONE self._alarm_handle = alarms.add_alarm(self, time_span, self._alarm_callback) self._alarm_data[self._alarm_handle] = best_work_data if time_span is not None and ( self._early_warning_callback is not None and self._early_warning_time_span is not None ) and self._early_warning_time_span > date_and_time.TimeSpan.ZERO: warning_time_span = time_span - self._early_warning_time_span if warning_time_span > date_and_time.TimeSpan.ZERO: logger.assert_log( self._early_warning_alarm_handle is None, 'Scheduler is setting an early warning alarm when the previous one has not fired.', owner='tingyul') self._early_warning_alarm_handle = alarms.add_alarm( self, warning_time_span, self._early_warning_alarm_callback)
def build_basic_elements(self, sequence=()): sequence = super().build_basic_elements(sequence=sequence) for sim in self.required_sims(): for social_group in sim.get_groups_for_sim_gen(): sequence = social_group.with_social_focus( self.sim, social_group._group_leader, (sim, ), sequence) suspended_modifiers_dict = self._generate_suspended_modifiers_dict() if gsi_handlers.interaction_archive_handlers.is_archive_enabled(self): start_time = services.time_service().sim_now else: start_time = None def interaction_start(_): self._suspend_modifiers(suspended_modifiers_dict) self.apply_interaction_cost() performance.counters.add_counter('PerfNumSubInteractions', 1) self._add_interaction_to_targets() if gsi_handlers.interaction_archive_handlers.is_archive_enabled( self): gsi_handlers.interaction_archive_handlers.archive_interaction( self.sim, self, 'Start') def interaction_end(_): if start_time is not None: self.duration = (services.time_service().sim_now - start_time).in_minutes() self._remove_interaction_from_targets() self.sim.update_last_used_interaction(self) self._resume_modifiers(suspended_modifiers_dict) return build_critical_section_with_finally(interaction_start, sequence, interaction_end)
def interaction_end(_): if start_time is not None: self.duration = (services.time_service().sim_now - start_time).in_minutes() self._remove_interaction_from_targets() self.sim.update_last_used_interaction(self) self._resume_modifiers(suspended_modifiers_dict)
def _spawn_next_sim(self): self._cleanup_submitted_requests() denied_requests = self._prune_and_sort_submitted_requests() for request in denied_requests: self._customer_denied_notification(request, 'Request was pruned.') if not self._submitted_requests: return False active_household = services.active_household() only_spawn_game_breakers_and_selectables = not self._cap_cheat_enabled and (active_household is None or self._number_of_instantiated_npcs >= self.npc_soft_cap) request = None if not only_spawn_game_breakers_and_selectables: request = self._submitted_requests[0] else: for request_candidate in self._submitted_requests: if not request_candidate._sim_info.is_selectable: if request_candidate._game_breaker: request = request_candidate break request = request_candidate break if request is None: return False else: should_spawn = False if request._sim_info.is_selectable or (request._game_breaker or self._mode == _SpawningMode.BATCH_SPAWNING) or self._gui_smoke_notification_enabled: should_spawn = True elif self._next_spawn_time <= services.time_service().sim_now: should_spawn = True if should_spawn: if request._sim_info.is_npc: self._number_of_instantiated_npcs += 1 self._spawn_requested_sim(request) return True return False
def _on_leaving_situation(self, end_work_reason): service_npc_type = self._service_npc_type household = self._hiring_household try: now = services.time_service().sim_now time_worked = now - self._service_start_time time_worked_in_hours = time_worked.in_hours() if self._had_preroll_work: cost = service_npc_type.get_cost(time_worked_in_hours) else: cost = 0 if cost > 0: (paid_amount, billed_amount) = service_npc_type.try_charge_for_service(household, cost) end_work_reason = ServiceNpcEndWorkReason.NOT_PAID else: paid_amount = 0 billed_amount = 0 self._send_end_work_notification(end_work_reason, paid_amount, billed_amount) service_record = household.get_service_npc_record(service_npc_type.guid64) service_record.time_last_finished_service = now if end_work_reason == ServiceNpcEndWorkReason.FIRED: service_sim = self.service_sim() if service_record is not None: service_record.add_fired_sim(service_sim.id) service_record.remove_preferred_sim(service_sim.id) while end_work_reason in ServiceNpcSituation.CANCEL_SERVICE_LEAVING_REASONS: services.current_zone().service_npc_service.cancel_service(household, service_npc_type) except Exception as e: logger.exception('Exception while executing _on_leaving_situation for situation {}', self, exc=e) finally: if not self._is_recurring: services.current_zone().service_npc_service.cancel_service(household, service_npc_type) return end_work_reason
def join_career(self, career_history=None): resolver = SingleSimResolver(self._sim_info) (new_level, new_user_level, current_track) = self.get_career_entry_level(career_history=career_history, resolver=resolver) self._level = new_level self._user_level = new_user_level if self._company_name is None: self._company_name = self.get_random_company_name_hash() if current_track is None: self._current_track = self.start_track else: self._current_track = current_track self._join_time = services.time_service().sim_now self._reset_career_objectives(self._current_track, new_level) self.career_start() loot = self.current_level_tuning.loot_on_join if loot is not None: resolver = SingleSimResolver(self._sim_info) loot.apply_to_resolver(resolver) self._give_rewards_for_skipped_levels() with telemetry_helper.begin_hook(career_telemetry_writer, TELEMETRY_HOOK_CAREER_START, sim=self._sim_info) as hook: hook.write_int(TELEMETRY_CAREER_ID, self.guid64) hook.write_int(TELEMETRY_CAREER_LEVEL, self._user_level) hook.write_guid(TELEMETRY_TRACK_ID, self._current_track.guid64) hook.write_int(TELEMETRY_TRACK_LEVEL, new_level) if not self.get_is_school(): (_, first_work_time, _) = self.get_next_work_time() self.send_career_message(self.career_messages.join_career_notification, first_work_time)
def _create_work_session_alarms(self): self._end_work_handle = alarms.add_alarm(self, self.time_until_end_of_work() + TimeSpan.ONE, self._end_work_callback) if not self.attended_work: now = services.time_service().sim_now late_time = self.get_late_time() if now < late_time: self._late_for_work_handle = alarms.add_alarm(self, late_time - now + TimeSpan.ONE, self._late_for_work_callback)
def is_work_time(self): if self._current_work_start is None: return False current_time = services.time_service().sim_now if current_time.time_between_week_times(self._current_work_start, self._current_work_end): return True return False
def get_career_entry_level(self, career_history=None, resolver=None): if career_history is None or self.guid64 not in career_history: level = int(self.start_level_modifiers.get_max_modifier(resolver)) max_level = len(self.start_track.career_levels) level = sims4.math.clamp(0, level, max_level - 1) return (level, level + 1, None) history = career_history[self.guid64] new_level = history.career_level new_user_level = history.user_level time_left = history.time_left current_track_uid = history.track_uid current_track = services.get_instance_manager(sims4.resources.Types.CAREER_TRACK).get(current_track_uid) new_level -= self.levels_lost_on_leave new_user_level -= self.levels_lost_on_leave current_time = services.time_service().sim_now time_gone_from_career = current_time - time_left days_gone_from_career = time_gone_from_career.in_days() if self.days_to_level_loss > 0: levels_to_lose = int(days_gone_from_career/self.days_to_level_loss) new_level -= levels_to_lose new_user_level -= levels_to_lose if new_level < 0: new_level = 0 if new_user_level < 1: new_user_level = 1 return (new_level, new_user_level, current_track)
def on_employee_clock_out(self, employee_sim_info, career_level=DEFAULT): career = self.get_employee_career(employee_sim_info) if career is not None: if self.on_employee_career_promotion in career.on_promoted: career.on_promoted.unregister( self.on_employee_career_promotion) if self.on_employee_career_demotion in career.on_demoted: career.on_demoted.unregister(self.on_employee_career_demotion) if employee_sim_info.sim_id not in self._employee_payroll: return (clock_in_time, payroll_data) = self._employee_payroll[employee_sim_info.sim_id] if clock_in_time is not None: career_level = self.get_employee_career_level( employee_sim_info) if career_level is DEFAULT else career_level if career_level is not None: clock_out_time = services.time_service().sim_now payroll_data[career_level] += (clock_out_time - clock_in_time).in_hours() self._employee_payroll[employee_sim_info.sim_id] = (None, payroll_data) employee_data = self.get_employee_data(employee_sim_info) if employee_data is not None: employee_data.remove_career_buff() else: logger.error( '{} is being clocked out but not registered as an employee.', employee_sim_info)
def _spawn_requested_sim(self, request): for other_request in tuple(self._submitted_requests): if request._is_request_for_same_sim(other_request): self._submitted_requests.remove(other_request) self._spawning_requests.append(other_request) for other_request in tuple(self._listening_requests): if request._is_request_for_same_sim(other_request): self._listening_requests.remove(other_request) self._spawning_requests.append(other_request) place_strategy = request._place_strategy success = sims.sim_spawner.SimSpawner.spawn_sim(request._sim_info, sim_position=place_strategy.position, sim_location=place_strategy.location, sim_spawner_tags=place_strategy.spawner_tags, spawn_point_option=place_strategy.spawn_point_option, saved_spawner_tags=place_strategy.saved_spawner_tags, spawn_action=place_strategy.spawn_action, from_load=request._from_load, spawn_point=place_strategy.spawn_point, spawn_at_lot=place_strategy.spawn_at_lot) if success: sim_info = request._sim_info if services.get_rabbit_hole_service().will_override_spin_up_action(sim_info.id): services.sim_info_manager().schedule_sim_spin_up_action(sim_info, SimZoneSpinUpAction.NONE) else: services.sim_info_manager().schedule_sim_spin_up_action(sim_info, request._spin_up_action) self._next_spawn_time = services.time_service().sim_now + self._spawn_cooldown message = 'Spawn Start' else: if request in self._spawning_requests: self._spawning_requests.remove(request) message = 'Spawn Failed' if gsi_handlers.sim_spawner_service_log.sim_spawner_service_log_archiver.enabled: request.log_to_gsi(message) logger.debug('{}: {}', message, request)
def get_season_info(_connection=None): content = services.season_service().season_content sims4.commands.output('Season: {}'.format(services.season_service().season), _connection) sims4.commands.output('GameClock Progress: {}'.format(content.get_progress(services.game_clock_service().now())), _connection) sims4.commands.output('Simulation Progress: {}'.format(content.get_progress(services.time_service().sim_now)), _connection) sims4.commands.output(content.info, _connection) return True
def _update(self): career = self.sim_info.career_tracker.get_at_work_career() if career is None: logger.error( 'CareerTone {} trying to update performance when Sim {} not at work', self, self.sim_info, owner='tingyul') return if career._upcoming_gig is not None and career._upcoming_gig.odd_job_tuning is not None: return now = services.time_service().sim_now elapsed = now - self._last_update_time self._last_update_time = now career.apply_performance_change(elapsed, self.performance_multiplier) career.resend_career_data() resolver = SingleSimResolver(self.sim_info) for entry in self.periodic_sim_filter_loot: chance = entry.chance.get_chance(resolver) * elapsed.in_hours() if random.random() > chance: continue services.sim_filter_service().submit_filter( entry.sim_filter, self._sim_filter_loot_response, callback_event_data=entry, requesting_sim_info=self.sim_info, gsi_source_fn=self.get_sim_filter_gsi_name)
def save_data(self, household_msg): for utility in Utilities: while self.is_utility_delinquent(utility): household_msg.gameplay_data.delinquent_utilities.append(utility) for (bill_source, cost) in self._additional_bill_costs.items(): with ProtocolBufferRollback(household_msg.gameplay_data.additional_bill_costs) as additional_bill_cost: additional_bill_cost.bill_source = bill_source additional_bill_cost.cost = cost household_msg.gameplay_data.can_deliver_bill = self._can_deliver_bill household_msg.gameplay_data.put_bill_in_hidden_inventory = self._put_bill_in_hidden_inventory if self.current_payment_owed is not None: household_msg.gameplay_data.current_payment_owed = self.current_payment_owed current_time = services.time_service().sim_now if self._bill_timer_handle is not None: time = max((self._bill_timer_handle.finishing_time - current_time).in_ticks(), 0) household_msg.gameplay_data.bill_timer = time elif self._bill_timer is not None: household_msg.gameplay_data.bill_timer = self._bill_timer if self._shutoff_handle is not None: time = max((self._shutoff_handle.finishing_time - current_time).in_ticks(), 0) household_msg.gameplay_data.shutoff_timer = time elif self._shutoff_timer is not None: household_msg.gameplay_data.shutoff_timer = self._shutoff_timer if self._warning_handle is not None: time = max((self._warning_handle.finishing_time - current_time).in_ticks(), 0) household_msg.gameplay_data.warning_timer = time elif self._warning_timer is not None: household_msg.gameplay_data.warning_timer = self._warning_timer
def debugvis_test(name, _connection=None): client = services.client_manager().get(_connection) sim = client.active_sim time = services.time_service().sim_now hour = time.hour() % 12*sims4.math.TWO_PI/12 minute = time.minute()*sims4.math.TWO_PI/60 a = sim.position + sims4.math.Vector3(0, 1, 0) b = a + sims4.math.Vector3(math.cos(hour), 0, math.sin(hour))*3 c = a + sims4.math.Vector3(math.cos(minute), 0, math.sin(minute))*4 with Context(name, routing_surface=sim.routing_surface) as layer: layer.set_color(Color.YELLOW) layer.add_segment(a, b, color=Color.CYAN) layer.add_segment(a, c, color=Color.RED) layer.add_point(a, size=0.2) layer.add_point(b, size=0.1, color=Color.BLUE) layer.add_point(c, size=0.1, color=Color.MAGENTA) layer.add_circle(a, 5, color=Color.GREEN) for i in range(12): theta = i*sims4.math.TWO_PI/12 x = sims4.math.Vector3(4.75*math.cos(theta), 0, 4.75*math.sin(theta)) color = sims4.color.interpolate(Color.YELLOW, Color.BLUE, i/11) layer.add_arrow(a + x, 0.5*sims4.math.PI - theta, end_arrow=False, color=color) layer.add_text_world(a + x, str(i), color_foreground=pseudo_random_color(i)) layer.add_text_screen(sims4.math.Vector2(4, 32), 'Displaying debug visualization tests.') for i in range(200): layer.add_text_object(sim, sims4.math.Vector3.ZERO(), str(i), bone_index=i) return 1
def _write_common_data(hook, sim=None, household=None, session_id=None): if sim is not None: if not hook.valid_for_npc and sim.is_npc: hook.disabled_hook = True sim_id = sim.id if household is None: household = sim.household mood = sim.get_mood() if mood is not None: sim_mood = mood.guid64 else: sim_mood = 0 else: sim_id = 0 sim_mood = 0 sim_classification = 0 if household is not None: household_id = household.id account = household.account if sim is not None: sim_classification = _classify_sim(sim, household) if session_id is None: zone_id = sims4.zone_utils.get_zone_id(can_be_none=True) if zone_id is not None: client = account.get_client(zone_id) if client is not None: session_id = client.id else: household_id = 0 if session_id is None: session_id = 0 time_service = services.time_service() sim_time = int(time_service.sim_now.absolute_seconds()) sims4.telemetry._write_common_data(hook, sim_id, household_id, session_id, sim_time, sim_mood, sim_classification)
def _send_service_npc(self, scheduler, alarm_data, situation_creation_params): household = situation_creation_params.hiring_household service_npc_type = situation_creation_params.service_npc_type if not self._auto_scheduled_services_enabled and service_npc_type.auto_schedule_on_client_connect(): return service_record = household.get_service_npc_record(service_npc_type.guid64) preferred_sim_id = service_record.get_preferred_sim_id() situation_type = service_npc_type.situation user_specified_data_id = situation_creation_params.user_specified_data_id now = services.time_service().sim_now if service_record.time_last_started_service is not None and alarm_data.start_time is not None: alarm_start_time_absolute = date_and_time_from_week_time(now.week(), alarm_data.start_time) if service_record.time_last_started_service >= alarm_start_time_absolute: return service_record.time_last_started_service = now service_record.time_last_finished_service = None duration = alarm_data.end_time - now.time_since_beginning_of_week() min_duration = service_npc_type.min_duration_left_for_arrival_on_lot() if duration < min_duration: service_npc_type.fake_perform(household) return min_duration = service_npc_type.min_work_duration() max_duration = service_npc_type.max_work_duration() duration = clamp(min_duration, duration.in_minutes(), max_duration) guest_list = SituationGuestList(True) if preferred_sim_id is not None: guest_list.add_guest_info(SituationGuestInfo.construct_from_purpose(preferred_sim_id, situation_type.default_job(), SituationInvitationPurpose.PREFERRED)) situation_creation_params_writer = PropertyStreamWriter() situation_creation_params_writer.write_uint64('household_id', household.id) situation_creation_params_writer.write_uint64('service_npc_type_id', service_npc_type.guid64) if user_specified_data_id is not None: situation_creation_params_writer.write_uint64('user_specified_data_id', user_specified_data_id) situation_creation_params_writer.write_bool('is_recurring', situation_creation_params.is_recurring) self._situation_id = services.get_zone_situation_manager().create_situation(situation_type, guest_list, user_facing=False, duration_override=duration, custom_init_writer=situation_creation_params_writer)
def update_pregnancy(self): if self.is_pregnant: if self._last_modified is not None: tracker = self._sim_info.get_tracker(self.PREGNANCY_COMMODITY) pregnancy_commodity = tracker.get_statistic(self.PREGNANCY_COMMODITY, add=True) if pregnancy_commodity.get_value() >= self.PREGNANCY_COMMODITY.max_value: self.create_offspring_data() for offspring_data in self.get_offspring_data_gen(): offspring_data.first_name = self._get_random_first_name(offspring_data) self.create_sim_info(offspring_data) self._show_npc_dialog() self.clear_pregnancy() else: delta_time = services.time_service().sim_now - self._last_modified delta = self.PREGNANCY_RATE*delta_time.in_minutes() pregnancy_commodity.add_value(delta) self._last_modified = services.time_service().sim_now
def get_sim_available_for_social(self): if self._cur_state is None or not self._cur_state._is_available_for_interruption(): return if services.time_service().sim_now < self._social_cooldown_until: return if self._walker is not None and self._walker.opacity < 1.0: return return self._walker
def _get_default_sleep_schedule_work_time(self, offset_time): now = services.time_service().sim_now if offset_time is not None: now += offset_time work_time = date_and_time.create_date_and_time(days=int(now.absolute_days()), hours=self.SLEEP_SCHEDULE.default_work_time.hour(), minutes=self.SLEEP_SCHEDULE.default_work_time.minute()) if work_time < now: work_time += date_and_time.create_time_span(days=1) return work_time
def on_activate(self, reader=None): logger.debug('Pizza delivery NPC is entering wait state.') super().on_activate(reader) self.owner._service_start_time = services.time_service().sim_now self.owner._set_job_role_state(self.owner.pizza_delivery_job.situation_job, self.owner.pizza_delivery_job.wait_to_deliver_state) timeout = self.owner.wait_for_customer_duration self._timeout_handle = alarms.add_alarm(self, clock.interval_in_sim_minutes(timeout), lambda _: self.timer_expired()) self._test_event_register(TestEvent.InteractionComplete)
def is_on_cooldown(self): if self._cooldown_time is None: return False now = services.time_service().sim_now if self._cooldown_time >= now: return True self._cooldown_time = None return False
def _start_alarm(self): self._stop_alarm() if not self._sims_running_interaction: return next_hour = interval_in_sim_hours(int(self._total_time_ran.in_hours()) + 1) time_till_completion = (next_hour - self._total_time_ran)/len(self._sims_running_interaction) self._alarm_handle = alarms.add_alarm(self, time_till_completion, self._on_hour_reached) self._last_started_time = services.time_service().sim_now