def request_passive_balloon(sim, time_now): if time_now - sim.next_passive_balloon_unlock_time > create_time_span( minutes=PassiveBalloons.BALLOON_LONG_LOCKOUT): lockout_time = random.randint(0, PassiveBalloons.BALLOON_RANDOM) sim.next_passive_balloon_unlock_time = services.time_service( ).sim_now + create_time_span(minutes=lockout_time) return balloon_requests = [] if len(PassiveBalloons.ROUTING_BALLOONS ) > PassiveBalloons.MAX_NUM_BALLOONS: sampled_balloon_tuning = random.sample( PassiveBalloons.ROUTING_BALLOONS, PassiveBalloons.MAX_NUM_BALLOONS) else: sampled_balloon_tuning = PassiveBalloons.ROUTING_BALLOONS for balloon_weight_pair in sampled_balloon_tuning: balloon_request = PassiveBalloons.create_passive_ballon_request( sim, balloon_weight_pair.balloon) if balloon_request is not None: balloon_requests.append( (balloon_weight_pair.weight, balloon_request)) if len(balloon_requests) > 0: choosen_balloon = sims4.random.weighted_random_item( balloon_requests) if choosen_balloon is not None: choosen_balloon.distribute() lockout_time = PassiveBalloons.BALLOON_LOCKOUT + random.randint( 0, PassiveBalloons.BALLOON_RANDOM) sim.next_passive_balloon_unlock_time = time_now + create_time_span( minutes=lockout_time)
def deactivate_set(self, whim_set, from_cheat=False, from_cancel=False): if whim_set.timeout_retest is not None and not from_cancel: resolver = event_testing.resolver.SingleSimResolver(self._sim_info) if resolver(whim_set.timeout_retest.objective_test): self.remove_alarm_handle(whim_set) self.alarm_handles[whim_set] = alarms.add_alarm( self, create_time_span(minutes=whim_set.active_timer), lambda _, this_whim_set=whim_set: self.deactivate_set( this_whim_set), False) return if whim_set in self.active_sets: self.active_sets.remove(whim_set) elif whim_set in self.active_chained_sets: self.active_chained_sets.remove(whim_set) self.remove_alarm_handle(whim_set) if whim_set.cooldown_timer == 0: self._sim_info.aspiration_tracker.reset_milestone(whim_set.guid64) elif whim_set not in self.sets_on_cooldown and not from_cheat: self.sets_on_cooldown.append(whim_set) self.alarm_handles[whim_set] = alarms.add_alarm( self, create_time_span(minutes=whim_set.cooldown_timer), lambda _, this_whim_set=whim_set: self.finish_cooldown( this_whim_set), False)
def _start_delayed_decay_timer(self): self.refresh_threshold_callback() if self._delayed_decay_timer is not None: alarms.cancel_alarm(self._delayed_decay_timer) self._delayed_decay_timer = None initial_delay = self._get_initial_delay() final_delay = self._get_final_delay() now = services.time_service().sim_now time_passed = 0 if self._time_of_last_value_change is not None: time_passed = now - self._time_of_last_value_change time_passed = time_passed.in_minutes() if time_passed < initial_delay: length = date_and_time.create_time_span(minutes=initial_delay - time_passed) self._delayed_decay_timer = alarms.add_alarm( self, length, self._display_decay_warning) elif time_passed < initial_delay + final_delay: time_into_final_delay = time_passed - initial_delay length = date_and_time.create_time_span(minutes=final_delay - time_into_final_delay) self._delayed_decay_timer = alarms.add_alarm( self, length, self._start_delayed_decay) else: self._start_delayed_decay(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 update_sleep_schedule(self): self._remove_sleep_schedule_buff() for alarm_handle in self._sleep_buff_alarms.keys(): alarms.cancel_alarm(alarm_handle) self._sleep_buff_alarms.clear() time_span_until_wakeup = self.get_time_until_next_wakeup() sleep_schedule = self._get_sleep_schedule() most_appropriate_buff = None for sleep_schedule_entry in sorted( sleep_schedule.schedule, key=lambda entry: entry.time_from_work_start, reverse=True): if time_span_until_wakeup.in_hours( ) <= sleep_schedule_entry.time_from_work_start: most_appropriate_buff = sleep_schedule_entry.buff else: time_until_buff_alarm = time_span_until_wakeup - create_time_span( hours=sleep_schedule_entry.time_from_work_start) alarm_handle = alarms.add_alarm( self, time_until_buff_alarm, self._add_buff_callback, True, create_time_span(hours=date_and_time.HOURS_PER_DAY)) self._sleep_buff_alarms[ alarm_handle] = sleep_schedule_entry.buff if most_appropriate_buff: if most_appropriate_buff.buff_type: self._sleep_buff_handle = self.owner.add_buff( most_appropriate_buff.buff_type) if self._sleep_buff_reset: alarms.cancel_alarm(self._sleep_buff_reset) self._sleep_buff_reset = alarms.add_alarm(self, time_span_until_wakeup, self._reset_alarms_callback)
def _create_auto_age_callback(self, delay=1): if self._auto_age_handle is not None: alarms.cancel_alarm(self._auto_age_handle) time_span_until_age_up = create_time_span(days=delay) if time_span_until_age_up.in_ticks() <= 0: time_span_until_age_up = create_time_span(minutes=1) self._auto_age_handle = alarms.add_alarm(self, time_span_until_age_up, self.callback_auto_age, False)
def activate_chained_set(self, last_whim_set, goal, inherited_target_sim_info): for whim_set in last_whim_set.connected_whim_sets: while whim_set not in self.active_chained_sets and whim_set not in self.sets_on_cooldown: self._whimset_target_map[whim_set] = inherited_target_sim_info self.active_chained_sets.append(whim_set) if whim_set in self.active_sets: self.active_sets.remove(whim_set) self.remove_alarm_handle(whim_set) self.alarm_handles[whim_set] = alarms.add_alarm( self, create_time_span(minutes=whim_set.active_timer), lambda _, this_whim_set=whim_set: self.deactivate_set( this_whim_set), False) if goal in last_whim_set.connected_whims: whim_set = last_whim_set.connected_whims[goal] if whim_set not in self.active_chained_sets and whim_set not in self.sets_on_cooldown: self._whimset_target_map[whim_set] = inherited_target_sim_info self.active_chained_sets.append(whim_set) if whim_set in self.active_sets: self.active_sets.remove(whim_set) self.remove_alarm_handle(whim_set) self.alarm_handles[whim_set] = alarms.add_alarm( self, create_time_span(minutes=whim_set.active_timer), lambda _, this_whim_set=whim_set: self.deactivate_set( this_whim_set), False)
def activate_sprinkler_system(self): object_manager = services.object_manager() self._sprinkler_system_objects.update(object_manager.get_objects_with_tag_gen(self.SPRINKLER_BOX_OBJECT_TAG)) if not self._sprinkler_system_objects: return time_span = date_and_time.create_time_span(minutes=self.SPRINKLER_ACTIVATION_TIME) repeating_time_span = date_and_time.create_time_span(minutes=self.SPRINKLER_RUN_TIME) self._sprinkler_alarm = alarms.add_alarm(self, time_span, self._sprinkler_alarm_callback, repeating=True, repeating_time_span=repeating_time_span)
def activate_fire_alarms(self): object_manager = services.object_manager() self._fire_alarm_objects = set(object_manager.get_objects_of_type_gen(self.FIRE_ALARM_OBJECT_DEF)) if not self._fire_alarm_objects: return time_span = date_and_time.create_time_span(minutes=self.FIRE_ALARM_CYCLE_TIME) repeating_time_span = date_and_time.create_time_span(minutes=self.FIRE_ALARM_CYCLE_TIME) self._fire_alarm_alarm = alarms.add_alarm(self, time_span, self._fire_alarm_callback, repeating=True, repeating_time_span=repeating_time_span)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._start_and_end_times = set() for (day, day_enabled) in self.days_available.items(): if day_enabled: days_as_time_span = date_and_time.create_time_span(days=day) start_time = self.start_time + days_as_time_span end_time = start_time + date_and_time.create_time_span(hours=self.duration) self._start_and_end_times.add((start_time, end_time))
def _career_situation_callback(self, scheduler, alarm_data, extra_data): if not self._sim_info.is_instanced() or self._sim_info.is_npc: return num_situations = len(self.current_level_tuning.situation_list) if num_situations > 0 and not self.currently_at_work: self._career_situation = self.current_level_tuning.situation_list[random.randint(0, num_situations - 1)] self.send_career_message(self.career_messages.career_situation_start_notification, self._career_situation) self.set_career_situation_available(True) self._career_situation_alarm = alarms.add_alarm(self, create_time_span(hours=self._career_situation.available_time), lambda _: self.set_career_situation_available(False)) self._situation_scheduler.add_cooldown(create_time_span(days=self.current_level_tuning.situation_cooldown))
def __init__(self, **kwargs): super().__init__(**kwargs) self._start_and_end_times = set() for (day, day_enabled) in self.days_available.items(): while day_enabled: days_as_time_span = date_and_time.create_time_span(days=day) start_time = self.start_time + days_as_time_span end_time = start_time + date_and_time.create_time_span( hours=self.duration) self._start_and_end_times.add((start_time, end_time))
def attach_to_owner(self, owner, callback): sim = owner.get_participant(self.who) if sim is None: return offset_time = date_and_time.create_time_span(hours=self.hours_prior_to_schedule_start) time_span_until_work_start_time = sim.get_time_until_next_wakeup(offset_time=offset_time) if time_span_until_work_start_time.in_ticks() <= 0: logger.error('Wakeup time is in the past.', owner='rez') time_span_until_work_start_time += date_and_time.create_time_span(days=1) self._interval = time_span_until_work_start_time.in_minutes() return super().attach_to_owner(owner, callback)
def on_startup(self): super().on_startup() emergency_tuning = self._get_current_level_tuning() if emergency_tuning is not None: self._emergency_alarm_handle = alarms.add_alarm( self, create_time_span( minutes=emergency_tuning.inital_lockout_in_sim_minutes), self._on_create_emergency_request, repeating=True, repeating_time_span=create_time_span( minutes=emergency_tuning.cool_down_in_sim_minutes))
def initialize_alarms(self): if self._buff_alarm is not None: alarms.cancel_alarm(self._buff_alarm) self._buff_alarm = alarms.add_alarm( self, create_time_span(minutes=TelemetryTuning.BUFF_ALARM_TIME), self.buff_telemetry_report, True) if self._emotion_relationship_alarm is not None: alarms.cancel_alarm(self._emotion_relationship_alarm) self._emotion_relationship_alarm = alarms.add_alarm( self, create_time_span(minutes=TelemetryTuning.EMOTION_REL_ALARM_TIME), self.emotion_relation_telemetry_report, True)
def _create_spawner_alarm(self): if self._spawner_data_spawn_index >= len(self._spawner_data): return time_span = date_and_time.create_time_span( minutes=randint(SpawnerInitializer.SPAWN_DELAYED_START, SpawnerInitializer.SPAWN_DELAYED_END)) repeating_time_span = date_and_time.create_time_span( minutes=SpawnerInitializer.SPAWN_FREQUENCY) self._spawn_object_alarm = alarms.add_alarm( self, time_span, self._spawn_one_object, repeating=True, repeating_time_span=repeating_time_span)
def _create_weather_transition_element(cls, time, new_transition_data, old_transition_data, key, event_element, previous_event_element, using_new_delay): if event_element is None: value = 0.0 start_time = time rate = 0 else: value = event_element.range.random_float() start_time = time + create_time_span( minutes=event_element.start_delay) rate = event_element.start_rate start_value = services.weather_service().get_weather_element_value( key, time) if value == 0.0 and start_value == 0.0: return using_new_delay if rate != 0: using_new_delay = True old_data = old_transition_data.get(key, None) if old_data is not None and old_data.end_value > value: if previous_event_element is not None: using_new_delay = False start_time = time + create_time_span( minutes=previous_event_element.end_delay) rate = previous_event_element.end_rate else: logger.error( 'Weather transition element: old data end value greater than new value for key {}, but there is no old element\nOld data:{}\nOld event:{}\nNew Event:{}', key, old_data, services.weather_service()._current_event, cls) if rate == 0: if old_transition_data[key].end_value != 0.0: logger.error( "Weather transition element unable to calculate rate, and final destination of existing transition isn't 0" ) end_time = time + create_time_span( minutes=cls.FALLBACK_TRANSITION_TIME) new_transition_data[key] = WeatherElementTuple( start_value, time, 0.0, end_time) else: new_transition_data[key] = old_transition_data[key] return using_new_delay transition_duration = abs(start_value - value) / rate end_time = start_time + create_time_span(minutes=transition_duration) new_transition_data[key] = WeatherElementTuple(start_value, start_time, value, end_time) return using_new_delay
def _update_cooldowns(self): now = services.time_service().sim_now for (drama_node, time) in tuple(self._cooldown_nodes.items()): cooldown = drama_node.cooldown if cooldown is None: continue cooldown_length = date_and_time.create_time_span(hours=cooldown.duration) time += cooldown_length if time < now: del self._cooldown_nodes[drama_node] for (cooldown_group, time) in tuple(self._cooldown_groups.items()): cooldown_length = date_and_time.create_time_span(hours=BaseDramaNode.COOLDOWN_GROUPS[cooldown_group].duration) time += cooldown_length if time < now: del self._cooldown_groups[cooldown_group]
def update_age_callbacks(self): age_transition_data = self.get_age_transition_data(self.age) if self._is_aging_disabled(): self._age_time = age_transition_data.get_age_duration(self) self._age_progress.decay_enabled = False if self._almost_can_age_handle is not None: alarms.cancel_alarm(self._almost_can_age_handle) self._almost_can_age_handle = None if self._can_age_handle is not None: alarms.cancel_alarm(self._can_age_handle) self._can_age_handle = None if self._auto_age_handle is not None: alarms.cancel_alarm(self._auto_age_handle) self._auto_age_handle = None return self._update_age_trait(self._base.age) self._age_time = age_transition_data.get_age_duration(self) self._age_progress.decay_enabled = True if self.is_elder: bonus_days = self._get_bonus_days() else: bonus_days = 0 aging_service = services.get_aging_service() setting_multiplier = aging_service.get_speed_multiple( self._age_speed_setting) self._age_progress.set_modifier(setting_multiplier) age_time = self.days_until_ready_to_age() warn_time = age_time - age_transition_data.age_transition_warning / setting_multiplier auto_age_time = age_time + (age_transition_data.age_transition_delay + bonus_days) / setting_multiplier if self._almost_can_age_handle is not None: alarms.cancel_alarm(self._almost_can_age_handle) if warn_time >= 0: self._almost_can_age_handle = alarms.add_alarm( self, create_time_span(days=warn_time), self.callback_almost_ready_to_age, cross_zone=True) if self._can_age_handle is not None: alarms.cancel_alarm(self._can_age_handle) if age_time >= 0: self._can_age_handle = alarms.add_alarm( self, create_time_span(days=age_time), self.callback_ready_to_age, cross_zone=True) self._create_auto_age_callback(delay=max(0, auto_age_time)) self.send_age_progress()
def _do_behavior(timeline): target = self.interaction.get_participant(self.participant) if target is None: return False target.fade_out() timespan = date_and_time.create_time_span( minutes=target.FADE_DURATION) yield element_utils.run_child(timeline, elements.SleepElement(timespan)) sim = self.interaction.sim target.set_household_owner_id(sim.household_id) replace_reserve = False if target.in_use_by(sim, owner=self.interaction): target.release(sim, self.interaction) replace_reserve = True try: if target == self.interaction.target: self.interaction.set_target(None) if self.use_sim_inventory: sim.inventory_component.system_add_object(target, sim) else: build_buy.move_object_to_household_inventory(target) finally: target.opacity = 1 if replace_reserve: target.reserve(sim, self.interaction) return True
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 __init__(self): self._alarm_handle = alarms.add_alarm( self, create_time_span(minutes=self.FIREMETER_FREQUENCY), self._firemeter_callback, repeating=True, use_sleep_time=False)
def resume(self): now = services.time_service().sim_now time_since_started = now - self._selected_time if time_since_started < create_time_span(minutes=self.pre_festival_duration): self._setup_pre_festival_alarm() else: self._try_and_start_festival()
def start_situation(self): services.get_persistence_service().lock_save(self) super().start_situation() self._change_state(PrepareForBattleSituationState()) motherplant = self._get_motherplant() motherplant.set_stat_value(self.player_health_statistic, 0, add=True) motherplant.set_stat_value(self.motherplant_health_statisic, self.motherplant_health_statisic.max_value, add=True) for state_value in self.states_to_set_on_start: motherplant.set_state(state_value.state, state_value) statistic_tracker = motherplant.statistic_tracker self._statistic_watcher_handle = statistic_tracker.add_watcher( self._on_statistic_updated) self._setup_situation_meters() self._zombie_attack_alarm_handle = alarms.add_alarm( self, create_time_span(minutes=self.zombie_fight_interaction_timer), self._zombie_attack, repeating=True) for custom_key in itertools.chain( self.victory_interaction_of_interest.custom_keys_gen(), self.retreat_interaction_of_interest.custom_keys_gen()): custom_key_tuple = (TestEvent.InteractionComplete, custom_key) self._registered_test_events.add(custom_key_tuple) services.get_event_manager().register_with_custom_key( self, TestEvent.InteractionComplete, custom_key)
def on_startup(self): super().on_startup() self._situation_alarm_handle = alarms.add_alarm( self, create_time_span(minutes=self.DESIRED_SITUATION_INTERVAL), self._on_desired_situation_request, repeating=True)
def refresh_goals(self, completed_goal=None, debug_goal=None, debug_target=None, request_single_goal=False, request_single_delay=0, emotion_only=False): if completed_goal is not None: logger.debug('Whim completed for {}: {}', self._sim_info, completed_goal, owner='jjacobson') op = distributor.ops.SetWhimComplete(completed_goal.guid64) Distributor.instance().add_op(self._sim_info, op) if completed_goal.score > 0: self._sim_info.add_whim_bucks(completed_goal.score, SetWhimBucks.WHIM) self._remove_goal_from_current_order(completed_goal) completed_goal.unregister_for_on_goal_completed_callback( self._on_goal_completed) del self._realized_goals[completed_goal] completed_goal.decommision() if request_single_delay == 0 or debug_goal is not None: self.offer_goals(debug_goal=debug_goal, debug_target=debug_target, request_single_goal=request_single_goal, emotion_only=emotion_only) else: delay_alarm = alarms.add_alarm( self, create_time_span(minutes=request_single_delay), self._delayed_offer_goals, False) self.delay_alarm_handles.append(delay_alarm) self._send_goals_update()
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 _make_guests_watch(self, _): static_commodity_list = [ self.owner.guest.watch_wedding_static_commodity ] object_list = list( self.owner.all_sims_in_job_gen(self.owner.betrothed.situation_job)) for sim_info in tuple(self._guest_sim_infos_to_force_watch): sim = sim_info.get_sim_instance() if sim is None: self._guest_sim_infos_to_force_watch.remove(sim_info) InteractionCancelCompatibility.cancel_interactions_for_reason( sim, InteractionCancelReason.WEDDING, FinishingType.WEDDING, 'Interaction was cancelled due to the wedding situation.') autonomy_request = AutonomyRequest( sim, autonomy_mode=FullAutonomy, object_list=object_list, static_commodity_list=static_commodity_list, limited_autonomy_allowed=False, autonomy_mode_label_override='WeddingMakeGuestsWatch') selected_interaction = services.autonomy_service( ).find_best_action(autonomy_request) while selected_interaction is not None: if AffordanceObjectPair.execute_interaction( selected_interaction): self._guest_sim_infos_to_force_watch.remove(sim_info) if self._guest_sim_infos_to_force_watch: self._alarm_handle = alarms.add_alarm( self, create_time_span(minutes=self.MAKE_GUESTS_WATCH_ALARM_TIME), self._make_guests_watch)
def _initialize_alarms(self): repeating_time_span = date_and_time.create_time_span( minutes=self.bowling_venue.situation_alarm_interval) self._bowling_situation_alarm_handle = alarms.add_alarm( self, date_and_time.create_time_span(minutes=5), self._find_available_lane_and_start_situations, repeating=True, repeating_time_span=repeating_time_span) if self.bowling_venue.moonlight_on_off_schedule: self._moonlight_change() time_of_day = services.time_service().sim_now self._moonlight_alarm_handle = alarms.add_alarm( self, self._get_time_span_to_next_moonlight_schedule(time_of_day), self._moonlight_change)
def _reset_decay_alarm(self): self._destroy_decay_alarm() if self._should_decay() and self.delay_until_decay_is_applied is not None: logger.debug('Resetting decay alarm for track {} for {}.', self, self.tracker.relationship) delay_time_span = date_and_time.create_time_span(minutes=self.delay_until_decay_is_applied) self._decay_alarm_handle = alarms.add_alarm(self, delay_time_span, self._decay_alarm_callback) self.decay_enabled = False
class TimeOfDayComponent(Component, HasTunableFactory, component_name=types.TIME_OF_DAY_COMPONENT): __qualname__ = 'TimeOfDayComponent' DAILY_REPEAT = date_and_time.create_time_span(hours=24) FACTORY_TUNABLES = { 'state_changes': TunableMapping( description= '\n A mapping from state to times of the day when the state should be \n set to a tuned value.\n ', key_type=TunableStateTypeReference( description='The state to be set.'), value_type=TunableList( description='List of times to modify the state at.', tunable=TunableTuple(start_time=TunableRange( float, 0, description= 'The start time (24 hour clock time) for the Day_Time state.', minimum=0, maximum=24), value=TunableStateValueReference( description='New state value.')))) } def __init__(self, owner, *, state_changes): super().__init__(owner) self.state_changes = state_changes self.alarm_handles = [] def _add_alarm(self, cur_state, game_clock, state, change): time_to_day = game_clock.time_until_hour_of_day(change.start_time) def change_state(_): self.owner.set_state(state, change.value) self.alarm_handles.append( alarms.add_alarm(self.owner, time_to_day, change_state, repeating=True, repeating_time_span=self.DAILY_REPEAT)) if cur_state is None or time_to_day > cur_state[0]: return (time_to_day, change.value) return cur_state def on_add(self): game_clock_service = services.game_clock_service() for (state, changes) in self.state_changes.items(): current_state = None for change in changes: current_state = self._add_alarm(current_state, game_clock_service, state, change) while current_state is not None: self.owner.set_state(state, current_state[1]) def on_remove(self): for handle in self.alarm_handles: alarms.cancel_alarm(handle)
def time_until_hour_of_day(self, hour_of_day): cur_hour = self.now().hour() if cur_hour <= hour_of_day: hours_from_now = hour_of_day - cur_hour else: hours_from_now = 24 - cur_hour + hour_of_day return date_and_time.create_time_span(hours=hours_from_now)
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 _do_behavior(timeline): target = self.interaction.get_participant(self.participant) if target is None: return False target.fade_out() timespan = date_and_time.create_time_span(minutes=target.FADE_DURATION) yield element_utils.run_child(timeline, elements.SleepElement(timespan)) sim = self.interaction.sim target.set_household_owner_id(sim.household_id) replace_reserve = False if target.in_use_by(sim, owner=self.interaction): target.release(sim, self.interaction) replace_reserve = True try: if target == self.interaction.target: self.interaction.set_target(None) if self.use_sim_inventory: sim.inventory_component.system_add_object(target, sim) else: build_buy.move_object_to_household_inventory(target) finally: target.opacity = 1 if replace_reserve: target.reserve(sim, self.interaction) return True
class _SituationManagerSimData: __qualname__ = '_SituationManagerSimData' BLACKLISTED_MAX_SPAN = date_and_time.create_time_span(hours=8) def __init__(self, sim_id): self._sim_id = sim_id self._created_time = None self._blacklist_until = date_and_time.DATE_AND_TIME_ZERO def set_created_time(self, created_time): self._created_time = created_time @property def created_time(self): return self._created_time def blacklist(self, blacklist_until=None): if blacklist_until is None: self._blacklist_until = services.time_service( ).sim_now + self.BLACKLISTED_MAX_SPAN else: self._blacklist_until = blacklist_until @property def is_blacklisted(self): return services.time_service().sim_now < self._blacklist_until def get_remaining_blacklisted_time_span(self): if self.is_blacklisted == False: return date_and_time.TimeSpan.ZERO return self._blacklist_until - services.time_service().sim_now
def refresh_aging_updates(self, sim_info): sim_info.send_age_progress_bar_update() if self._aging_update_alarm is None: self._age_update_handle = alarms.add_alarm( self, create_time_span(days=AgingTuning.AGE_PROGRESS_UPDATE_TIME), self._send_household_aging_update, True)
def force_neighbors_home(_connection=None): client = services.client_manager().get_first_client() active_household = client.household if active_household is not None: active_household_home_zone_id = active_household.home_zone_id active_household_home_world_id = services.get_persistence_service( ).get_world_id_from_zone(active_household_home_zone_id) send_home = active_household_home_zone_id == services.current_zone().id blacklist_all_jobs_time = services.time_service( ).sim_now + date_and_time.create_time_span(days=7) for sim_info in services.sim_info_manager().values(): if sim_info.is_selectable: continue sim_info_home_zone_id = sim_info.household.home_zone_id sim_info_home_world_id = services.get_persistence_service( ).get_world_id_from_zone(sim_info_home_zone_id) if sim_info_home_world_id == active_household_home_world_id: services.get_zone_situation_manager( ).add_sim_to_auto_fill_blacklist( sim_info.id, None, blacklist_all_jobs_time=blacklist_all_jobs_time) if send_home: if sim_info.zone_id != active_household_home_zone_id: if sim_info.zone_id != sim_info_home_zone_id: sim_info.inject_into_inactive_zone( sim_info_home_zone_id)
def _destroy_layer_gradually(self): self.alarm_handle = alarms.add_alarm( self, TimeSpan.ZERO, self._destroy_objects_callback, repeating=True, repeating_time_span=create_time_span(minutes=self.timer_interval))
def deactivate_set(self, whim_set, from_cheat=False, from_cancel=False): if whim_set.timeout_retest is not None and not from_cancel: resolver = event_testing.resolver.SingleSimResolver(self._sim_info) if resolver(whim_set.timeout_retest.objective_test): self.remove_alarm_handle(whim_set) self.alarm_handles[whim_set] = alarms.add_alarm(self, create_time_span(minutes=whim_set.active_timer), lambda _, this_whim_set=whim_set: self.deactivate_set(this_whim_set), False) return if whim_set in self.active_sets: self.active_sets.remove(whim_set) elif whim_set in self.active_chained_sets: self.active_chained_sets.remove(whim_set) self.remove_alarm_handle(whim_set) if whim_set.cooldown_timer == 0: self._sim_info.aspiration_tracker.reset_milestone(whim_set.guid64) elif whim_set not in self.sets_on_cooldown and not from_cheat: self.sets_on_cooldown.append(whim_set) self.alarm_handles[whim_set] = alarms.add_alarm(self, create_time_span(minutes=whim_set.cooldown_timer), lambda _, this_whim_set=whim_set: self.finish_cooldown(this_whim_set), False)
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 _run_interaction_gen(self, timeline): sim = self.sim end_time = services.time_service().sim_now + create_time_span(hours=8) fake_alarm_data = AlarmData(None, end_time, None, False) default_user_specified_data_id = self._service_tuning.get_default_user_specified_data_id() creation_data = ServiceNpcSituationCreationParams(sim.household, self._service_tuning, user_specified_data_id=default_user_specified_data_id, is_recurring=False) services.current_zone().service_npc_service._send_service_npc(None, fake_alarm_data, creation_data) return True
def on_activate(self, reader=None): super().on_activate(reader) self._test_event_register(TestEvent.InteractionComplete) guest_tuple = self.owner.guest self.owner._set_job_role_state(guest_tuple.situation_job, guest_tuple.guest_ceremony_role_state) self.owner._set_job_role_state(self.owner.betrothed.situation_job, self.owner.betrothed.betrothed_ceremony_role_state) self._guest_sim_infos_to_force_watch = [sim.sim_info for sim in self.owner.all_sims_in_job_gen(guest_tuple.situation_job)] self._alarm_handle = alarms.add_alarm(self, create_time_span(minutes=self.MAKE_GUESTS_WATCH_ALARM_TIME), self._make_guests_watch)
def start_evaporation(self): if self._evaporate_alarm_handle is not None: alarms.cancel_alarm(self._evaporate_alarm_handle) if self.is_outside: time = self.outdoor_evaporation_time.random_float() else: time = self.indoor_evaporation_time.random_float() self._evaporate_alarm_handle = alarms.add_alarm(self, date_and_time.create_time_span(minutes=time), self.evaporate)
def activate_chained_set(self, last_whim_set, goal, inherited_target_sim_info): for whim_set in last_whim_set.connected_whim_sets: while whim_set not in self.active_chained_sets and whim_set not in self.sets_on_cooldown: self._whimset_target_map[whim_set] = inherited_target_sim_info self.active_chained_sets.append(whim_set) if whim_set in self.active_sets: self.active_sets.remove(whim_set) self.remove_alarm_handle(whim_set) self.alarm_handles[whim_set] = alarms.add_alarm(self, create_time_span(minutes=whim_set.active_timer), lambda _, this_whim_set=whim_set: self.deactivate_set(this_whim_set), False) if goal in last_whim_set.connected_whims: whim_set = last_whim_set.connected_whims[goal] if whim_set not in self.active_chained_sets and whim_set not in self.sets_on_cooldown: self._whimset_target_map[whim_set] = inherited_target_sim_info self.active_chained_sets.append(whim_set) if whim_set in self.active_sets: self.active_sets.remove(whim_set) self.remove_alarm_handle(whim_set) self.alarm_handles[whim_set] = alarms.add_alarm(self, create_time_span(minutes=whim_set.active_timer), lambda _, this_whim_set=whim_set: self.deactivate_set(this_whim_set), False)
def activate_set(self, whim_set, is_cheat=False): if whim_set in self.sets_on_cooldown: return if whim_set not in self.active_sets and whim_set not in self.active_chained_sets: if __debug__ and not is_cheat: self._whimset_objective_map[whim_set] = self._sim_info.aspiration_tracker.latest_objective self.active_sets.append(whim_set) self.remove_alarm_handle(whim_set) self.alarm_handles[whim_set] = alarms.add_alarm(self, create_time_span(minutes=whim_set.active_timer), lambda _, this_whim_set=whim_set: self.deactivate_set(this_whim_set), False) refresh_delay = whim_set.new_whim_delay.random_int() self.refresh_goals(request_single_goal=True, request_single_delay=refresh_delay)
def request_passive_balloon(sim, time_now): if time_now - sim.next_passive_balloon_unlock_time > create_time_span(minutes=PassiveBalloons.BALLOON_LONG_LOCKOUT): lockout_time = random.randint(0, PassiveBalloons.BALLOON_RANDOM) sim.next_passive_balloon_unlock_time = services.time_service().sim_now + create_time_span(minutes=lockout_time) return balloon_requests = [] if len(PassiveBalloons.ROUTING_BALLOONS) > PassiveBalloons.MAX_NUM_BALLOONS: sampled_balloon_tuning = random.sample(PassiveBalloons.ROUTING_BALLOONS, PassiveBalloons.MAX_NUM_BALLOONS) else: sampled_balloon_tuning = PassiveBalloons.ROUTING_BALLOONS for balloon_weight_pair in sampled_balloon_tuning: balloon_request = PassiveBalloons.create_passive_ballon_request(sim, balloon_weight_pair.balloon) while balloon_request is not None: balloon_requests.append((balloon_weight_pair.weight, balloon_request)) if len(balloon_requests) > 0: choosen_balloon = sims4.random.weighted_random_item(balloon_requests) if choosen_balloon is not None: choosen_balloon.distribute() lockout_time = PassiveBalloons.BALLOON_LOCKOUT + random.randint(0, PassiveBalloons.BALLOON_RANDOM) sim.next_passive_balloon_unlock_time = time_now + create_time_span(minutes=lockout_time)
def _make_guests_watch(self, _): static_commodity_list = [self.owner.guest.watch_wedding_static_commodity] object_list = list(self.owner.all_sims_in_job_gen(self.owner.betrothed.situation_job)) for sim_info in tuple(self._guest_sim_infos_to_force_watch): sim = sim_info.get_sim_instance() if sim is None: self._guest_sim_infos_to_force_watch.remove(sim_info) InteractionCancelCompatibility.cancel_interactions_for_reason(sim, InteractionCancelReason.WEDDING, FinishingType.WEDDING, 'Interaction was cancelled due to the wedding situation.') autonomy_request = AutonomyRequest(sim, autonomy_mode=FullAutonomy, object_list=object_list, static_commodity_list=static_commodity_list, limited_autonomy_allowed=False, autonomy_mode_label_override='WeddingMakeGuestsWatch') selected_interaction = services.autonomy_service().find_best_action(autonomy_request) while selected_interaction is not None: if AffordanceObjectPair.execute_interaction(selected_interaction): self._guest_sim_infos_to_force_watch.remove(sim_info) if self._guest_sim_infos_to_force_watch: self._alarm_handle = alarms.add_alarm(self, create_time_span(minutes=self.MAKE_GUESTS_WATCH_ALARM_TIME), self._make_guests_watch)
def autonomy_distance_estimates_perform_timed_run(time_to_run_in_seconds:int=180, _connection=None): global g_distance_estimate_alarm_handle if g_distance_estimate_alarm_handle is not None: autonomy_distance_estimates_disable(_connection=_connection) alarms.cancel_alarm(g_distance_estimate_alarm_handle) g_distance_estimate_alarm_handle = None autonomy_distance_estimates_enable(_connection=_connection) def _finish_test_and_write_file(_): global g_distance_estimate_alarm_handle autonomy_distance_estimates_log_file(_connection=_connection) autonomy_distance_estimates_disable(_connection=_connection) g_distance_estimate_alarm_handle = None time_span = date_and_time.create_time_span(minutes=time_to_run_in_seconds) g_distance_estimate_alarm_handle = alarms.add_alarm_real_time(services.autonomy_service(), time_span, _finish_test_and_write_file)
def fake_perform(cls, household): num_modified = super().fake_perform(household) minutes_taken = num_modified*cls._fake_perform_minutes_per_object time_taken = create_time_span(minutes=minutes_taken) total_cost = cls.get_cost(time_taken.in_hours()) if total_cost > 0: (paid_amount, billed_amount) = cls.try_charge_for_service(household, total_cost) else: (paid_amount, billed_amount) = (0, 0) if cls._fake_perform_notification is not None: first_instanced_sim = next(household.instanced_sims_gen(allow_hidden_flags=ALL_HIDDEN_REASONS), None) if first_instanced_sim is not None: dialog = cls._fake_perform_notification(first_instanced_sim) if dialog is not None: dialog.show_dialog(additional_tokens=(paid_amount, billed_amount, paid_amount + billed_amount)) return num_modified
def _do_behavior(self): request_type = self._request_type.request_type service_npc = self._request_type.service if service_npc is None: return service_npc_service = services.current_zone().service_npc_service if request_type == self.HIRE: finishing_time = service_npc_service.request_service(self._household, service_npc, user_specified_data_id=self._service_npc_user_specified_data_id, is_recurring=self._recurring) if self.notification is not None and finishing_time is not None: finishing_time = finishing_time + create_time_span(minutes=self.MINUTES_ADD_TO_SERVICE_ARRIVAL) notification_element = self.notification(self.interaction) notification_element.show_notification(additional_tokens=(finishing_time,)) elif request_type == self.CANCEL: service_npc_service.cancel_service(self._household, service_npc) if self.notification is not None: notification_element = self.notification(self.interaction) notification_element._do_behavior()
def force_neighbors_home(_connection=None): client = services.client_manager().get_first_client() active_household = client.household if active_household is not None: active_household_home_zone_id = active_household.home_zone_id active_household_home_world_id = services.get_persistence_service().get_world_id_from_zone(active_household_home_zone_id) send_home = active_household_home_zone_id == services.current_zone().id blacklist_until = services.time_service().sim_now + date_and_time.create_time_span(days=7) for sim_info in services.sim_info_manager().values(): if sim_info.is_selectable: pass sim_info_home_zone_id = sim_info.household.home_zone_id sim_info_home_world_id = services.get_persistence_service().get_world_id_from_zone(sim_info_home_zone_id) while sim_info_home_world_id == active_household_home_world_id: services.get_zone_situation_manager().add_sim_to_auto_fill_blacklist(sim_info.id, blacklist_until=blacklist_until) if send_home and sim_info.zone_id != active_household_home_zone_id and sim_info.zone_id != sim_info_home_zone_id: sim_info.inject_into_inactive_zone(sim_info_home_zone_id)
def refresh_goals(self, completed_goal=None, debug_goal=None, debug_target=None, request_single_goal=False, request_single_delay=0, emotion_only=False): if completed_goal is not None: logger.debug('Whim completed for {}: {}', self._sim_info, completed_goal, owner='jjacobson') op = distributor.ops.SetWhimComplete(completed_goal.guid64) Distributor.instance().add_op(self._sim_info, op) if completed_goal.score > 0: self._sim_info.add_whim_bucks(completed_goal.score, SetWhimBucks.WHIM) self._remove_goal_from_current_order(completed_goal) completed_goal.unregister_for_on_goal_completed_callback(self._on_goal_completed) del self._realized_goals[completed_goal] completed_goal.decommision() if request_single_delay == 0 or debug_goal is not None: self.offer_goals(debug_goal=debug_goal, debug_target=debug_target, request_single_goal=request_single_goal, emotion_only=emotion_only) else: delay_alarm = alarms.add_alarm(self, create_time_span(minutes=request_single_delay), self._delayed_offer_goals, False) self.delay_alarm_handles.append(delay_alarm) self._send_goals_update()
def update_sleep_schedule(self): self._remove_sleep_schedule_buff() for alarm_handle in self._sleep_buff_alarms.keys(): alarms.cancel_alarm(alarm_handle) self._sleep_buff_alarms.clear() time_span_until_wakeup = self.get_time_until_next_wakeup() most_appropriate_buff = None for sleep_schedule_entry in sorted(self.SLEEP_SCHEDULE.schedule, key=lambda entry: entry.time_from_work_start, reverse=True): if time_span_until_wakeup.in_hours() <= sleep_schedule_entry.time_from_work_start: most_appropriate_buff = sleep_schedule_entry.buff else: time_until_buff_alarm = time_span_until_wakeup - date_and_time.create_time_span(hours=sleep_schedule_entry.time_from_work_start) alarm_handle = alarms.add_alarm(self, time_until_buff_alarm, self._add_buff_callback, True, date_and_time.create_time_span(hours=date_and_time.HOURS_PER_DAY)) self._sleep_buff_alarms[alarm_handle] = sleep_schedule_entry.buff if most_appropriate_buff and most_appropriate_buff.buff_type: self._sleep_buff_handle = self.owner.add_buff(most_appropriate_buff.buff_type) if self._sleep_buff_reset: alarms.cancel_alarm(self._sleep_buff_reset) self._sleep_buff_reset = alarms.add_alarm(self, time_span_until_wakeup, self._reset_alarms_callback)
def career_start(self, is_load=False): if self.current_level_tuning.situation_schedule is not None: self._situation_scheduler = self.current_level_tuning.situation_schedule(start_callback=self._career_situation_callback, schedule_immediate=False) if self.current_level_tuning.work_schedule is not None: if self.career_messages.career_early_warning_time is not None: early_warning_time_span = date_and_time.create_time_span(hours=self.career_messages.career_early_warning_time) else: early_warning_time_span = None self._work_scheduler = self.current_level_tuning.work_schedule(start_callback=self._start_work_callback, schedule_immediate=False, early_warning_callback=self._early_warning_callback, early_warning_time_span=early_warning_time_span) self._add_performance_statistics() if is_load: self.restore_career_session() self.restore_tones() else: if self.current_level_tuning.work_outfit.outfit_tags: self._sim_info.generate_career_outfit(tag_list=list(self.current_level_tuning.work_outfit.outfit_tags)) sim = self._get_sim() if sim is not None: sim.update_sleep_schedule() services.get_event_manager().process_event(test_events.TestEvent.CareerEvent, sim_info=self._sim_info, career=self) self._add_statistic_metric_listeners()
def handle_career_loot(self, hours_worked): reward = self.collect_rewards(hours_worked) span_worked = create_time_span(hours=hours_worked) services.get_event_manager().process_event(test_events.TestEvent.WorkdayComplete, sim_info=self._sim_info, career=self, time_worked=span_worked.in_ticks(), money_made=reward)
def _start_activate_super_speed_three_alarm(self): if self._try_activate_super_speed_three_alarm is None: logger.debug('[SS3] try_activate_super_speed_three_alarm STARTED') self._try_activate_super_speed_three_alarm = alarms.add_alarm(self, date_and_time.create_time_span(minutes=self.TRY_ACTIVATE_SUPER_SPEED_THREE_PING_IN_SIM_MINUTES), self._try_activate_super_speed_three_alarm_callback, repeating=True)