def _on_goal_completed(self, goal, goal_completed): if not goal_completed: self._goals_dirty = True self._send_goals_update() return services.get_event_manager().process_event( test_events.TestEvent.WhimCompleted, sim_info=self._sim_info, whim_completed=goal) with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_WHIM_EVENT, sim=self._sim_info) as hook: hook.write_int(TELEMETRY_WHIM_EVENT_TYPE, TelemetryWhimEvents.COMPLETED) hook.write_guid(TELEMETRY_WHIM_GUID, goal.guid64) prev_goal_set = self._realized_goals.get(goal, None) self._completed_goals[type(goal)] = (goal, prev_goal_set) inherited_target_sim_info = goal._get_actual_target_sim_info() refresh_delay = prev_goal_set.new_whim_delay.random_int() if prev_goal_set not in prev_goal_set.connected_whim_sets: self.deactivate_set(prev_goal_set) self.activate_chained_set(prev_goal_set, goal, inherited_target_sim_info) self._goals_dirty = True logger.debug('Goal completed: {}, from Whim Set: {}', goal.__class__.__name__, self._realized_goals[goal].__name__) self.refresh_goals(goal, request_single_goal=True, request_single_delay=refresh_delay)
def on_removed_from_inventory(self): owner = self._last_inventory_owner if owner.is_sim: services.get_event_manager().process_event(TestEvent.OnInventoryChanged, sim_info=owner.sim_info) inventory = owner.inventory_component if owner is not None and inventory is not None and inventory.inventory_type not in (InventoryType.MAILBOX, InventoryType.HIDDEN): self.owner.new_in_inventory = False
def _register_for_tuned_global_policy_events(self): active_global_policies = self._active_global_policy_modifiers is not None for policy in self.global_policy_value_mapping: if active_global_policies and policy in self._active_global_policy_modifiers: continue services.get_event_manager().register_with_custom_key( self, TestEvent.GlobalPolicyProgress, policy)
def _destroy(self): super()._destroy() self.clear_current_object() services.get_persistence_service().unlock_save(self) if self.auto_clear_debt_event is not None: services.get_event_manager().unregister_single_event( self, self.auto_clear_debt_event)
def start_situation(self): services.get_persistence_service().lock_save(self) super().start_situation() self._change_state(_WaitForRepoPersonState()) if self.auto_clear_debt_event is not None: services.get_event_manager().register_single_event( self, self.auto_clear_debt_event)
def on_crafting_process_finished(self): self._add_hovertip() self.owner.update_commodity_flags() crafting_process = self._crafting_process if crafting_process is None: return recipe = crafting_process.recipe if self._use_base_recipe: recipe = recipe.get_base_recipe() skill_test = recipe.skill_test if crafting_process.crafter_sim_id is None: return sim_info = services.sim_info_manager().get( crafting_process.crafter_sim_id) created_object_quality = self.owner.get_state( CraftingTuning.QUALITY_STATE) if self.owner.has_state( CraftingTuning.QUALITY_STATE) else None created_object_masterwork = self.owner.get_state( CraftingTuning.MASTERWORK_STATE) if self.owner.has_state( CraftingTuning.MASTERWORK_STATE) else None services.get_event_manager().process_event( test_events.TestEvent.ItemCrafted, sim_info=sim_info, crafted_object=self.owner, skill=skill_test.skill if skill_test is not None else None, quality=created_object_quality, masterwork=created_object_masterwork)
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 load_street_layers(self, street_cls, editmode=False): resolver = GlobalResolver() tests_to_register = [] for tested_conditional_layer in street_cls.tested_conditional_layers: if editmode and not tested_conditional_layer.test_on_managed_world_edit_mode_load: continue self._tested_layer_processing_type[ tested_conditional_layer. conditional_layer] = tested_conditional_layer.process_after_event_handled tests = tested_conditional_layer.tests conditional_layer = tested_conditional_layer.conditional_layer should_be_loaded = tests.run_tests(resolver) is_loaded = self.is_layer_loaded(conditional_layer) if should_be_loaded: self._active_street_conditional_layers.add(conditional_layer) if not is_loaded: self.load_conditional_layer(conditional_layer) elif conditional_layer.client_only: self._set_client_layer(conditional_layer, True) elif not should_be_loaded and is_loaded: self._active_street_conditional_layers.discard( conditional_layer) self.destroy_conditional_layer(conditional_layer) for test in tests: key_events_for_conditional_layer = set( event for (event, _) in itertools.chain( test.get_test_events_to_register(), test.get_custom_event_registration_keys())) for key_event in key_events_for_conditional_layer: self._test_event_to_conditional_layers[key_event].append( (conditional_layer, tests)) tests_to_register.append(test) if tests_to_register: services.get_event_manager().register_tests( self, tests_to_register)
def _trigger_interaction_start_event(self): super()._trigger_interaction_start_event() if self.linked_interaction_type is None: sim = self.get_participant(ParticipantType.TargetSim) if sim is not None: services.get_event_manager().process_event(test_events.TestEvent.InteractionStart, sim_info=sim.sim_info, interaction=self, custom_keys=self.get_keys_to_process_events()) self._register_target_event_auto_update()
def add_buff(self, buff_type, buff_reason=None, update_mood=True, commodity_guid=None, replacing_buff=None, timeout_string=None, transition_into_buff_id=0, change_rate=None, immediate=False): replacement_buff_type = self._get_replacement_buff_type(buff_type) if replacement_buff_type is not None: return self.owner.add_buff(replacement_buff_type, buff_reason=buff_reason, update_mood=update_mood, commodity_guid=commodity_guid, replacing_buff=buff_type, timeout_string=timeout_string, transition_into_buff_id=transition_into_buff_id, change_rate=change_rate, immediate=immediate) (can_add, conflicting_buff_type) = self._can_add_buff_type(buff_type) if not can_add: return buff = self._active_buffs.get(buff_type) if buff is None: buff = buff_type(self.owner, commodity_guid, replacing_buff, transition_into_buff_id) self._active_buffs[buff_type] = buff buff.on_add(self.load_in_progress) self._update_chance_modifier() if update_mood: self._update_current_mood() if self.owner.household is not None: services.get_event_manager().process_event(test_events.TestEvent.BuffBeganEvent, sim_info=self.owner, sim_id=self.owner.sim_id, buff=buff_type) self.register_auto_update(self.owner, buff_type) self.on_buff_added(buff_type) handle_id = self._get_next_handle_id() buff.add_handle(handle_id, buff_reason=buff_reason) self.send_buff_update_msg(buff, True, change_rate=change_rate, immediate=immediate) if conflicting_buff_type is not None: self.remove_buff_by_type(conflicting_buff_type) return handle_id
def start_situation(self): end_situation = True if self._kick_out_reason in self.start_dialog_map: sim_info = services.sim_info_manager().get(self._host_sim_id) map_entry = self.start_dialog_map[self._kick_out_reason] if sim_info is not None: if map_entry is not None: resolver = SingleSimResolver(sim_info) dialog = map_entry(None, resolver) dialog.show_dialog() end_situation = False if self._kick_out_reason == UniversityHousingKickOutReason.BABY and not self._additional_sim_ids: logger.error( 'Attempting to kick sim out of university housing for {} without a valid parent', self._kick_out_reason, owner='bnguyen') if end_situation: self._self_destruct() services.get_persistence_service().lock_save(self) super().start_situation() self._change_state(self.preparation_state()) services.get_event_manager().register( self, (TestEvent.HouseholdSplitPanelClosed, )) services.get_event_manager().register( self, (TestEvent.SimEnrolledInUniversity, ))
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 on_zone_load(self): sim_info_manager = services.sim_info_manager() for (employee_type, employee_id_list) in self._employee_sim_ids.items(): for employee_id in employee_id_list: sim_info = sim_info_manager.get(employee_id) if sim_info is not None: self._employees[sim_info.sim_id] = BusinessEmployeeData( self, sim_info, employee_type) self._employee_sim_ids.clear() self.update_employees(add_career_remove_callback=True) for employee_uniform in itertools.chain( self._employee_uniform_data_male.values(), self._employee_uniform_data_female.values()): self._send_employee_uniform_data(employee_uniform) services.get_event_manager().register_single_event( self, TestEvent.SkillLevelChange) if not self._business_manager.is_active_household_and_zone(): return if self._business_manager.is_open: for sim_info in self.get_employees_on_payroll(): if self.get_employee_career(sim_info) is None: self.on_employee_clock_out(sim_info) (clock_in_time, _) = self._employee_payroll[sim_info.sim_id] if clock_in_time is not None: self._register_employee_callbacks(sim_info) employee_data = self.get_employee_data(sim_info) employee_data.add_career_buff()
def set_value(self, value, *args, from_load=False, interaction=None, **kwargs): old_points = self.get_value() old_user_value = self.get_user_value() value_to_set = value if not from_load: value_to_set = self._get_valid_value(value, old_user_value) minimum_level = self._get_minimum_decay_level() value_to_set = max(value_to_set, minimum_level) super().set_value(value_to_set, *args, from_load=from_load, interaction=interaction, **kwargs) new_user_value = self.get_user_value() if not from_load: self._handle_level_down(old_user_value, new_user_value) sim_info = self._tracker._owner new_points = self.get_value() stat_type = self.stat_type if old_points == self.initial_value or old_points != new_points: services.get_event_manager().process_event( TestEvent.StatValueUpdate, sim_info=sim_info, statistic=stat_type, custom_keys=(stat_type, )) self.send_commodity_progress_msg(is_rate_change=False) self.send_change_update_message(value - old_points, from_load=from_load) self.previous_event_level = new_user_value self.refresh_threshold_callback()
def _on_sim_added(self, sim_info): self.notify_dirty() services.get_event_manager().process_event( test_events.TestEvent.HouseholdChanged, sim_info=sim_info) for unlock in sim_info.build_buy_unlocks: self.add_build_buy_unlock(unlock) sim_info.refresh_age_settings()
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._possible_sims = set() services.get_event_manager().register_single_event( self, event_testing.test_events.TestEvent.PrerelationshipChanged) services.get_event_manager().register_single_event( self, event_testing.test_events.TestEvent.RelationshipChanged)
def clean_up(self): if self._favorites is not None: self._favorites = None services.get_event_manager().unregister_single_event( self, TestEvent.ObjectDestroyed) if len(self._favorite_stacks) > 0: self._favorite_stacks = []
def _create_serving(self): chef_station = self.get_staffed_object() if chef_station is None: logger.error('Trying to create the serving platter for the chef station but the situation has no Chef Station.') return if self._current_order is None: logger.error('Trying to create a meal for the chef to serve at the chef station but the situation has no current order.') return if isinstance(self._current_order, GroupOrder): if not self._current_order.is_canceled: serving_platter = self._create_and_slot_cooking_object(chef_station, ChefTuning.CHEF_STATION_SERVING_PLATTER_OBJECT, ChefTuning.CHEF_STATION_SERVE_SLOT_TYPE) self._current_order.assign_serving_from_chef(serving_platter) business_manager = services.business_service().get_business_manager_for_zone() if business_manager is not None: business_manager.calculate_and_apply_expense_for_group_order(self._current_order) self._zone_director.set_order_status(self._current_order, OrderStatus.ORDER_READY) else: self._chef_remove_order() else: ordered_recipe = self._current_order.ordered_recipe ordered_recipe_definition = ordered_recipe.final_product_definition created_order = self._create_and_slot_cooking_object(chef_station, ordered_recipe_definition, ChefTuning.CHEF_STATION_SERVE_SLOT_TYPE) for initial_state in reversed(ordered_recipe.final_product.initial_states): created_order.set_state(initial_state.state, initial_state, from_init=True) for apply_state in reversed(ordered_recipe.final_product.apply_states): created_order.set_state(apply_state.state, apply_state, from_init=True) crafting_process = CraftingProcess(crafter=self.get_staff_member(), recipe=ordered_recipe) crafting_process.setup_crafted_object(created_order, is_final_product=True) self._push_sim_to_pick_up_order(self._current_order.ordering_sim, created_order) services.get_event_manager().process_event(test_events.TestEvent.RestaurantOrderDelivered, sim_info=self._current_order.ordering_sim.sim_info) self._chef_remove_order()
def disable_situation_state(self, new_situation_state): self._locked_states.add(new_situation_state) if self._cur_state.situation_state == new_situation_state: self.try_set_next_state(self._cur_state) services.get_event_manager().process_event( TestEvent.AvailableDaycareSimsChanged, sim_info=self.service_sim().sim_info)
def npc_order_food_at_chef_station(opt_sim: OptionalTargetParam = None, chef_sim: OptionalTargetParam = None, _connection=None): sim = get_optional_target(opt_sim, _connection) if sim is None: sims4.commands.output("Sim {} doesn't exist.".format(opt_sim), _connection) return False chef_sim = get_optional_target(chef_sim, _connection) if chef_sim is None: sims4.commands.output("Chef {} doesn't exist.".format(chef_sim), _connection) return False chef_situation = restaurant_utils.get_chef_situation(chef_sim=chef_sim) if chef_situation is None: sims4.commands.output("Couldn't find a Chef Situation in this zone.") return False if chef_situation.menu_preset is not None: food_order = ChefsChoice.get_order_for_npc_sim_with_menu( sim, chef_situation.menu_preset) else: (food_order, _) = ChefsChoice.get_order_for_npc_sim(sim) chef_situation.add_direct_order(food_order, sim) services.get_event_manager().process_event( test_events.TestEvent.RestaurantFoodOrdered, sim_info=sim.sim_info) return True
def display_scholarship_info(self, subject): if self.SCHOLARSHIP_INFORMATION_SIGN.display_image is None or self.SCHOLARSHIP_INFORMATION_SIGN.background_image is None: logger.error( 'Attempting to show scholarship sign to ({}) when content is None.', subject) return sign_info = UI_pb2.DynamicSignView() sign_info.name = self.SCHOLARSHIP_INFORMATION_SIGN.title sign_info.image = sims4.resources.get_protobuff_for_key( self.SCHOLARSHIP_INFORMATION_SIGN.display_image) sign_info.background_image = sims4.resources.get_protobuff_for_key( self.SCHOLARSHIP_INFORMATION_SIGN.background_image) for sub_info in self.SCHOLARSHIP_INFORMATION_SIGN.sub_infos: with ProtocolBufferRollback(sign_info.activities) as activity_msg: if sub_info.icon is None: logger.error( 'Attempting to show scholarship sign to ({}) when sub_info icon is None.', subject) continue activity_msg.name = sub_info.name activity_msg.description = sub_info.desc activity_msg.icon = create_icon_info_msg( IconInfoData(sub_info.icon)) distributor = Distributor.instance() distributor.add_op( subject.sim_info, GenericProtocolBufferOp(Operation.DYNAMIC_SIGN_VIEW, sign_info)) services.get_event_manager().process_event( TestEvent.ScholarshipInfoSignShown, sim_info=subject)
def cleanup(self, from_service_stop=False): super().cleanup(from_service_stop=from_service_stop) if self._end_alarm_handle is not None: alarms.cancel_alarm(self._end_alarm_handle) self._lottery_sims.clear() services.get_event_manager().unregister_single_event( self, self.lottery_event)
def refresh_progress(self, sim_info=None): if sim_info is None: sim_info = self.owner_sim_info services.get_event_manager().process_test_events_for_objective_updates( sim_info) self._send_objectives_update_to_client() self._send_tracker_to_client(init=True)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) reader = kwargs.get('reader', None) if reader: value = reader.read_uint32('test_int', 27) services.get_event_manager().register(self, self._goal_test.test_events)
def __init__(self, *args, reader=None, **kwargs): super().__init__(reader=reader, *args, **kwargs) self._total_time_ran = TimeSpan.ZERO self._last_started_time = None self._alarm_handle = None self._total_duration = interval_in_sim_hours(self._goal_test.duration) self._test_events = set() self._test_events.add( event_testing.test_events.TestEvent.InteractionStart) self._test_events.add( event_testing.test_events.TestEvent.InteractionComplete) services.get_event_manager().register(self, self._test_events) if reader is not None: duration_run = reader.read_uint64(self.DURATION_RUN, 0) self._total_time_ran = TimeSpan(duration_run) self._sims_running_interaction = set() if self._situation is None and self._sim_info is not None: self._sims_running_interaction.add(self._actor_ref().id) else: for sim in self._situation.all_sims_in_situation_gen(): while sim.si_state.is_running_affordance( self._goal_test.affordance): self._sims_running_interaction.add(sim.id) if self._sims_running_interaction: self._start_alarm()
def _germinate(self): plant = None try: plant = create_object(self.plant) location = self._find_germinate_location(plant) if location is None: logger.warn('Failed to germinate: No location found') plant.destroy(source=self.owner, cause='Failed to germinate: No location found') plant = None return False if self.owner.parent_slot is not None: self.owner.parent_slot.add_child(plant) else: plant.location = location plant.gardening_component.add_fruit(self.owner, sprouted_from=True) created_object_quality = self.owner.get_state(GardeningTuning.QUALITY_STATE_VALUE) current_household = services.owning_household_of_active_lot() if current_household is not None: plant.set_household_owner_id(current_household.id) services.get_event_manager().process_events_for_household(test_events.TestEvent.ItemCrafted, current_household, crafted_object=plant, skill=None, quality=created_object_quality, masterwork=None) if self.owner.in_use: self.owner.transient = True else: self.owner.destroy(source=self.owner, cause='Successfully germinated.') return except: logger.exception('Failed to germinate.') if plant is not None: plant.destroy(source=self.owner, cause='Failed to germinate.') plant = None return False return plant
def _update_timer_alarm(self, _): sim_info = self.owner_sim_info if sim_info is None: logger.error('No Sim info in AspirationTracker._update_timer_alarm') return self.update_timers() if sim_info.is_selected: services.get_event_manager().process_event(test_events.TestEvent.TestTotalTime, sim_info=sim_info)
def set_sim_available(self, sim_info, returning_sim_infos=()): household = sim_info.household daycare_previously_enabled = self.is_anyone_at_daycare(household) nanny_previously_enabled = False if daycare_previously_enabled else self.is_anyone_with_nanny(household) self._unavailable_sims.discard(sim_info) if daycare_previously_enabled or nanny_previously_enabled: self._disable_daycare_or_nanny_if_necessary(household, returning_sim_infos=returning_sim_infos) services.get_event_manager().process_event(TestEvent.AvailableDaycareSimsChanged, sim_info=sim_info)
def _on_set_sim_job(self, sim, job_type): super()._on_set_sim_job(sim, job_type) if job_type is self.target_job: self._target_sim_info = sim.sim_info services.get_event_manager().register(self, self.TEST_EVENTS) else: self._stalker_sim_info = sim.sim_info self._stalk_finish_ticks = services.time_service().sim_now.absolute_ticks() + create_time_span(minutes=self.time_to_chase.random_int()).in_ticks()
def trigger_test_event(self, sim_info, event): if sim_info is None: return services.get_event_manager().process_event( event, sim_info=sim_info, sim_id=self._relationship.sim_id, target_sim_id=self._relationship.target_sim_id)
def set_sim_unavailable(self, sim_info): household = sim_info.household nanny_previously_disabled = not self.is_anyone_with_nanny(household) daycare_previously_disabled = True if not nanny_previously_disabled else not self.is_anyone_at_daycare(household) self._unavailable_sims.add(sim_info) if nanny_previously_disabled or daycare_previously_disabled: self._enable_daycare_or_nanny_if_necessary(household) services.get_event_manager().process_event(TestEvent.AvailableDaycareSimsChanged, sim_info=sim_info)
def street_civic_policy_force_daily_vote(_connection=None): 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 services.get_event_manager().process_event( TestEvent.CivicPolicyDailyRandomVoting)
def on_loading_screen_animation_finished(self): logger.debug('on_loading_screen_animation_finished') services.game_clock_service().restore_saved_clock_speed() services.sim_info_manager().on_loading_screen_animation_finished() services.get_event_manager().process_events_for_household( test_events.TestEvent.SimTravel, services.active_household(), zone_id=self.id)
def _do_behavior(self): household = services.owning_household_of_active_lot() if household is None: return if not household.bills_manager.can_deliver_bill: return household.bills_manager.trigger_bill_notifications_from_delivery() services.get_event_manager().process_events_for_household(TestEvent.BillsDelivered, household)
def __init__(self, *args, reader=None, **kwargs): super().__init__(reader=reader, *args, **kwargs) self._total_simoleons_earned = 0 self._test_events = set() self._test_events.add(event_testing.test_events.TestEvent.SimoleonsEarned) services.get_event_manager().register(self, self._test_events) if reader is not None: simoleons_earned = reader.read_uint64(self.SIMOLEONS_EARNED, 0) self._total_simoleons_earned = simoleons_earned
def initialize_aspiration(self): if self.owner_sim_info is not None and not self.owner_sim_info.is_baby: track = self.active_track if track is not None: for (_, track_aspriation) in track.get_aspirations(): while not self.owner_sim_info.aspiration_tracker.milestone_completed(track_aspriation.guid64): self._activate_aspiration(track_aspriation) break services.get_event_manager().process_event(test_events.TestEvent.AspirationTrackSelected, sim_info=self.owner_sim_info)
def check_add_collection_item(self, household, obj_id, obj_def_id): (collectable_id, _collectible_data) = ObjectCollectionData.get_collection_info_by_definition(obj_def_id) if collectable_id is None: return False if obj_def_id not in self._collections: self._collections[obj_def_id] = collectable_id self.check_collection_complete(collectable_id) services.get_event_manager().process_events_for_household(test_events.TestEvent.CollectedSomething, household, collected_id=collectable_id) msg_type = UI_pb2.CollectibleItemUpdate.TYPE_ADD self.send_collection_msg(msg_type, collectable_id, household.id, obj_def_id, obj_id=obj_id) return True
def complete_pregnancy(self): services.get_event_manager().process_event(TestEvent.OffspringCreated, sim_info=self._sim_info, offspring_created=self.offspring_count) for tuning_data in self.MULTIPLE_OFFSPRING_CHANCES: while tuning_data.size == self.offspring_count: (parent_a, parent_b) = self.get_parents() if parent_a is parent_b: screen_slam = tuning_data.screen_slam_one_parent else: screen_slam = tuning_data.screen_slam_two_parents if screen_slam is not None: screen_slam.send_screen_slam_message(self._sim_info, parent_a, parent_b) break
def complete_milestone(self, aspiration, sim_info): aspiration_type = aspiration.aspiration_type() if aspiration_type == AspriationType.FULL_ASPIRATION: sim_info = self._owner_ref() if not (aspiration.is_child_aspiration and sim_info.is_child): return super().complete_milestone(aspiration, sim_info) if aspiration.reward is not None: aspiration.reward.give_reward(sim_info) track = self.active_track if track is None: logger.error('Active track is None when completing full aspiration.') return if aspiration in track.aspirations.values(): if aspiration.screen_slam is not None: aspiration.screen_slam.send_screen_slam_message(sim_info, sim_info, aspiration.display_name, track.display_text) if all(self.milestone_completed(track_aspiration.guid64) for track_aspiration in track.aspirations.values()): if track.reward is not None: reward_payout = track.reward.give_reward(sim_info) else: reward_payout = () reward_text = LocalizationHelperTuning.get_bulleted_list(None, *(reward.get_display_text() for reward in reward_payout)) dialog = track.notification(sim_info, SingleSimResolver(sim_info)) dialog.show_dialog(icon_override=(track.icon, None), secondary_icon_override=(None, sim_info), additional_tokens=(reward_text,), event_id=aspiration.guid64) next_aspiration = track.get_next_aspriation(aspiration) if next_aspiration is not None: self._activate_aspiration(next_aspiration) for objective in next_aspiration.objectives: while objective.set_starting_point(self.data_object): self.update_objective(objective.guid64, 0, objective.goal_value(), objective.is_goal_value_money) else: self._active_aspiration = None with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_COMPLETE_MILESTONE, sim=sim_info.get_sim_instance()) as hook: hook.write_enum('type', aspiration.aspiration_type()) hook.write_guid('guid', aspiration.guid64) services.get_event_manager().process_event(test_events.TestEvent.UnlockEvent, sim_info=sim_info, unlocked=aspiration) elif aspiration_type == AspriationType.FAMILIAL: super().complete_milestone(aspiration, sim_info) for relationship in aspiration.target_family_relationships: family_member_sim_id = sim_info.get_relation(relationship) family_member_sim_info = services.sim_info_manager().get(family_member_sim_id) while family_member_sim_info is not None: services.get_event_manager().process_event(test_events.TestEvent.FamilyTrigger, sim_info=family_member_sim_info, trigger=aspiration) elif aspiration_type == AspriationType.WHIM_SET: self._whimsets_to_reset.add(aspiration.guid64) super().complete_milestone(aspiration, sim_info) self._owner_ref().whim_tracker.activate_set(aspiration) elif aspiration_type == AspriationType.NOTIFICATION: dialog = aspiration.notification(sim_info, SingleSimResolver(sim_info)) dialog.show_dialog(event_id=aspiration.guid64) super().complete_milestone(aspiration, sim_info) else: super().complete_milestone(aspiration, sim_info)
def _on_spawn_sim_for_zone_spin_up_completed(self, client): for sim_info in self.values(): if sim_info.is_instanced(allow_hidden_flags=ALL_HIDDEN_REASONS) or sim_info.is_selectable: sim_info.commodity_tracker.start_low_level_simulation() sim_info.set_default_data() while sim_info.is_instanced(allow_hidden_flags=ALL_HIDDEN_REASONS) and not sim_info.is_npc: sim_info.aspiration_tracker.refresh_progress(sim_info) client.refresh_achievement_data() services.get_event_manager().unregister_unused_handlers() for sim_info in client.selectable_sims: while sim_info.is_instanced(allow_hidden_flags=ALL_HIDDEN_REASONS): sim_info.aspiration_tracker.initialize_aspiration() sim_info.career_tracker.activate_career_aspirations() self._set_default_genealogy() for sim_info in self.values(): sim_info.relationship_tracker.send_relationship_info()
def on_crafting_process_finished(self): self._add_hovertip() self.owner.update_commodity_flags() crafting_process = self._crafting_process if crafting_process is None: return recipe = crafting_process.recipe if self._use_base_recipe: recipe = recipe.get_base_recipe() skill_test = recipe.skill_test if crafting_process.crafter_sim_id is None: return sim_info = services.sim_info_manager().get(crafting_process.crafter_sim_id) created_object_quality = self.owner.get_state(CraftingTuning.QUALITY_STATE) if self.owner.has_state(CraftingTuning.QUALITY_STATE) else None created_object_masterwork = self.owner.get_state(CraftingTuning.MASTERWORK_STATE) if self.owner.has_state(CraftingTuning.MASTERWORK_STATE) else None services.get_event_manager().process_event(test_events.TestEvent.ItemCrafted, sim_info=sim_info, crafted_object=self.owner, skill=skill_test.skill if skill_test is not None else None, quality=created_object_quality, masterwork=created_object_masterwork)
def remove_buff(self, handle_id, update_mood=True, immediate=False, on_destroy=False): for (buff_type, buff_entry) in self._active_buffs.items(): while handle_id in buff_entry.handle_ids: should_remove = buff_entry.remove_handle(handle_id) if should_remove: del self._active_buffs[buff_type] buff_entry.on_remove(not self.load_in_progress and not on_destroy) if not on_destroy: if update_mood: self._update_current_mood() self._update_chance_modifier() self.send_buff_update_msg(buff_entry, False, immediate=immediate) services.get_event_manager().process_event(test_events.TestEvent.BuffEndedEvent, sim_info=self.owner, sim_id=self.owner.sim_id, buff=buff_type) if buff_type in self.buff_update_alarms: self.remove_auto_update(buff_type) self.on_buff_removed(buff_type) break
def remove_buff_entry(self, buff_entry, on_destroy=False): if buff_entry is not None: if buff_entry.commodity is not None: tracker = self.owner.get_tracker(buff_entry.commodity) commodity_inst = tracker.get_statistic(buff_entry.commodity) if commodity_inst is not None and commodity_inst.core: if not on_destroy: logger.callstack('Attempting to explicitly remove the buff {}, which is given by a core commodity. This would result in the removal of a core commodity and will be ignored.', buff_entry, owner='tastle', level=sims4.log.LEVEL_ERROR) return tracker.remove_statistic(buff_entry.commodity, on_destroy=on_destroy) elif buff_entry.buff_type in self._active_buffs: buff_entry.on_remove(on_destroy) del self._active_buffs[buff_entry.buff_type] if not on_destroy: self._update_chance_modifier() self._update_current_mood() self.send_buff_update_msg(buff_entry, False) services.get_event_manager().process_event(test_events.TestEvent.BuffEndedEvent, sim_info=self.owner, buff=type(buff_entry), sim_id=self.owner.id)
def _on_goal_completed(self, goal, goal_completed): if not goal_completed: self._goals_dirty = True self._send_goals_update() return services.get_event_manager().process_event(test_events.TestEvent.WhimCompleted, sim_info=self._sim_info, whim_completed=goal) with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_WHIM_EVENT, sim=self._sim_info) as hook: hook.write_int(TELEMETRY_WHIM_EVENT_TYPE, TelemetryWhimEvents.COMPLETED) hook.write_guid(TELEMETRY_WHIM_GUID, goal.guid64) prev_goal_set = self._realized_goals.get(goal, None) self._completed_goals[type(goal)] = (goal, prev_goal_set) inherited_target_sim_info = goal._get_actual_target_sim_info() refresh_delay = prev_goal_set.new_whim_delay.random_int() if prev_goal_set not in prev_goal_set.connected_whim_sets: self.deactivate_set(prev_goal_set) self.activate_chained_set(prev_goal_set, goal, inherited_target_sim_info) self._goals_dirty = True logger.debug('Goal completed: {}, from Whim Set: {}', goal.__class__.__name__, self._realized_goals[goal].__name__) self.refresh_goals(goal, request_single_goal=True, request_single_delay=refresh_delay)
def activate(cls): client = services.client_manager().get_first_client() active_sim = client.active_sim if cls.gameplay_immediate_test is not None: resolver = event_testing.resolver.SingleSimResolver(active_sim.sim_info) if resolver(cls.gameplay_immediate_test): cls.satisfy() else: return for buff_ref in cls.buffs: active_sim.add_buff_from_op(buff_ref.buff_type, buff_reason=buff_ref.buff_reason) if cls.gameplay_test is not None: services.get_event_manager().register_tests(cls, [cls.gameplay_test]) if cls.commodities_to_solve: context = InteractionContext(active_sim, InteractionContext.SOURCE_SCRIPT_WITH_USER_INTENT, priority.Priority.High, bucket=InteractionBucketType.DEFAULT) for commodity in cls.commodities_to_solve: if not active_sim.queue.can_queue_visible_interaction(): break autonomy_request = autonomy.autonomy_request.AutonomyRequest(active_sim, autonomy_mode=autonomy.autonomy_modes.FullAutonomy, commodity_list=(commodity,), context=context, consider_scores_of_zero=True, posture_behavior=AutonomyPostureBehavior.IGNORE_SI_STATE, distance_estimation_behavior=AutonomyDistanceEstimationBehavior.ALLOW_UNREACHABLE_LOCATIONS, allow_opportunity_cost=False, autonomy_mode_label_override='Tutorial') selected_interaction = services.autonomy_service().find_best_action(autonomy_request) AffordanceObjectPair.execute_interaction(selected_interaction)
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 remove_bit(self, bit, notify_client=True): logger.assert_raise(bit is not None, 'Error: Sim Id: {} trying to remove a None relationship bit to Sim_Id: {}.'.format(self._sim_id, self._target_sim_id)) if bit not in self._bits: logger.debug("Attempting to remove bit for {} that doesn't exist: {}", self, bit) return sim_info = self.find_sim_info() bit_instance = self._bits[bit] if self.suppress_client_updates or sim_info is not None: with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_REMOVE_BIT, sim=sim_info) as hook: hook.write_int(TELEMETRY_FIELD_TARGET_ID, self._target_sim_id) hook.write_int(TELEMETRY_FIELD_REL_ID, self.ID) hook.write_int(TELEMETRY_FIELD_BIT_ID, bit.guid64) try: services.get_event_manager().process_event(event_testing.test_events.TestEvent.RemoveRelationshipBit, sim_info=sim_info, relationship_bit=bit, sim_id=self._sim_id, target_sim_id=self._target_sim_id) except Exception: logger.warn('Threw error while attempting to process achievement on bit add. If you used a cheat, this is fine.', owner='rez') sim = sim_info.get_sim_instance() if sim is not None: target_sim_info = self.find_target_sim_info() if target_sim_info is not None: bit_instance.on_remove_from_relationship(sim, target_sim_info) if bit is Relationship.MARRIAGE_RELATIONSHIP_BIT: sim_info.update_spouse_sim_id(None) del self._bits[bit] self._cached_depth_dirty = True logger.debug('Removed bit {} for {}', bit, self) timeout_data = self._find_timeout_data_by_bit(bit) if timeout_data is not None: timeout_data.cancel_alarm() self._bit_timeouts.remove(timeout_data) if bit.remove_on_threshold: listener = bit_instance.remove_conditional_removal_listener() if listener is not None: self._bit_track_tracker.remove_listener(listener) else: logger.error("Bit {} is meant to have a listener on track {} but it doesn't for {}.".format(bit, bit.remove_on_threshold.track, self)) if sim_info: bit_instance.remove_appropriateness_buffs(sim_info) if notify_client is True: self._notify_client()
def __init__(self, *args, reader=None, **kwargs): super().__init__(reader=reader, *args, **kwargs) self._total_time_ran = TimeSpan.ZERO self._last_started_time = None self._alarm_handle = None self._total_duration = interval_in_sim_hours(self._goal_test.duration) self._test_events = set() self._test_events.add(event_testing.test_events.TestEvent.InteractionStart) self._test_events.add(event_testing.test_events.TestEvent.InteractionComplete) services.get_event_manager().register(self, self._test_events) if reader is not None: duration_run = reader.read_uint64(self.DURATION_RUN, 0) self._total_time_ran = TimeSpan(duration_run) self._sims_running_interaction = set() if self._situation is None and self._sim_info is not None: self._sims_running_interaction.add(self._actor_ref().id) else: for sim in self._situation.all_sims_in_situation_gen(): while sim.si_state.is_running_affordance(self._goal_test.affordance): self._sims_running_interaction.add(sim.id) if self._sims_running_interaction: self._start_alarm()
def on_enter(self): super().on_enter() zone = services.current_zone() zone_spin_up_service = zone.zone_spin_up_service zone.venue_service.setup_special_event_alarm() zone.ambient_service.begin_walkbys() client = zone_spin_up_service._client_connect_data.client if client is not None: with telemetry_helper.begin_hook( zone_telemetry_writer, TELEMETRY_HOOK_ZONE_LOAD, household=client.household) as hook: (player_sims, npc_sims) = services.sim_info_manager( ).get_player_npc_sim_count() hook.write_int(TELEMETRY_FIELD_PLAYER_COUNT, player_sims) hook.write_int(TELEMETRY_FIELD_NPC_COUNT, npc_sims) from event_testing import test_events for sim_info in client.selectable_sims: services.get_event_manager().process_event( test_events.TestEvent.LoadingScreenLifted, sim_info=sim_info) client.household.telemetry_tracker.initialize_alarms() return _ZoneSpinUpStateResult.DONE
def generate_test_event_view_data(*args, zone_id:int=None, **kwargs): event_mgr = services.get_event_manager() all_events = [] for (key, handlers) in event_mgr._test_event_callback_map.items(): (event_enum, custom_key) = key event_data = {} registered = len(handlers) called = '?' cost = '?' event_data['event_enum'] = int(event_enum) event_data['event_name'] = str(event_enum) event_data['custom_key'] = str(custom_key) event_data['register_count'] = registered event_data['called_count'] = called event_data['cost'] = cost event_data['handlers'] = str(handlers) sub_data = [] for handle in handlers: handlers_data = {} handlers_data['handle'] = str(handle) sub_data.append(handlers_data) event_data['handles'] = sub_data all_events.append(event_data) return all_events
def _update_money(self, amount, reason, account_id, sim=None, tags=None, count_as_earnings=True, show_fx=True): if amount == 0: return self._funds = min(self._funds + amount, self.MAX_FUNDS) if self._funds < 0: logger.error('Negative funds amount ({}) not supported', self._funds) self._funds = 0 vfx_amount = amount if not show_fx: vfx_amount = 0 self.send_money_update(vfx_amount=vfx_amount, sim=sim, reason=reason) with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_FUNDS_CHANGE, sim=sim) as hook: hook.write_int(TELEMETRY_AMOUNT, amount) hook.write_int(TELEMETRY_REASON, reason) hook.write_int(TELEMETRY_FUND_AMOUNT, self._funds) if count_as_earnings and amount > 0: if sim is None: services.get_event_manager().process_events_for_household(test_events.TestEvent.SimoleonsEarned, self._household, simoleon_data_type=SimoleonData.TotalMoneyEarned, amount=amount, skill_used=None, tags=tags) else: services.get_event_manager().process_event(test_events.TestEvent.SimoleonsEarned, sim_info=sim.sim_info, simoleon_data_type=SimoleonData.TotalMoneyEarned, amount=amount, skill_used=None, tags=tags) services.get_event_manager().process_events_for_household(test_events.TestEvent.SimoleonsEarned, self._household, simoleon_data_type=SimoleonData.TotalMoneyEarned, amount=0, skill_used=None, tags=frozenset(), exclude_sim=sim.sim_info)
def decommision(self): services.get_event_manager().unregister(self, self._test_events) super().decommision()
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._test_events = set() self._test_events.add(test_events.TestEvent.LoadingScreenLifted) services.get_event_manager().register(self, self._test_events)
def deactivate(cls): if cls.gameplay_test is not None: services.get_event_manager().unregister_tests(cls, (cls.gameplay_test,))
def decommision(self): services.get_event_manager().unregister(self, self.purchased_object_test.test_events) super().decommision()
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 register_callbacks(cls): tests = [objective.objective_test for objective in cls.objectives] services.get_event_manager().register_tests(cls, tests)