예제 #1
0
 def _send_create_situation_telemetry(self, situation_type, situation_id,
                                      guest_list, hire_cost, zone_id):
     if hasattr(situation_type, 'guid64'):
         with telemetry_helper.begin_hook(
                 writer, TELEMETRY_HOOK_CREATE_SITUATION) as hook:
             hook.write_int('situ', situation_id)
             hook.write_int('host', guest_list.host_sim_id)
             hook.write_guid('type', situation_type.guid64)
             hook.write_bool('invi', guest_list.invite_only)
             hook.write_bool('hire', hire_cost)
             hook.write_bool(
                 'nzon', zone_id != 0
                 and services.current_zone().id != zone_id)
         sim_info_manager = services.sim_info_manager()
         if sim_info_manager is not None:
             for guest_infos in guest_list._job_type_to_guest_infos.values(
             ):
                 for guest_info in guest_infos:
                     if guest_info.sim_id == 0:
                         continue
                     guest_sim = sim_info_manager.get(guest_info.sim_id)
                     if guest_sim is None:
                         continue
                     client = services.client_manager(
                     ).get_client_by_household_id(guest_sim.household_id)
                     with telemetry_helper.begin_hook(
                             writer, TELEMETRY_HOOK_GUEST) as hook:
                         hook.write_int('situ', situation_id)
                         hook.write_guid('type', situation_type.guid64)
                         if client is None:
                             hook.write_int('npcg', guest_info.sim_id)
                         else:
                             hook.write_int('pcgu', guest_info.sim_id)
                             hook.write_guid('jobb',
                                             guest_info.job_type.guid64)
 def _create_NPC_hosted_situation(dialog):
     if not dialog.accepted:
         with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_SITUATION_REJECTED, sim=player_sim) as hook:
             hook.write_guid('type', chosen_situation.guid64)
         return
     guest_list = SituationGuestList(host_sim_id=NPC_sim_id)
     if chosen_situation.NPC_hosted_situation_use_player_sim_as_filter_requester:
         guest_list.filter_requesting_sim_id = player_sim.id
     guest_list.add_guest_info(SituationGuestInfo.construct_from_purpose(player_sim.id, chosen_situation.NPC_hosted_situation_player_job, SituationInvitationPurpose.INVITED))
     chosen_zone_id = chosen_situation.get_venue_location()
     services.get_zone_situation_manager().create_situation(chosen_situation, guest_list=guest_list, zone_id=chosen_zone_id)
     self.add_cooldown(self._cooldown)
     with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_SITUATION_ACCEPTED, sim=player_sim) as hook:
         hook.write_guid('type', chosen_situation.guid64)
예제 #3
0
 def request_client_disconnect_gen(timeline):
     try:
         zone = services.current_zone()
         if zone is not None:
             client_manager = zone.client_manager
             client = client_manager.get(session_id)
             logger.info('Client {0} starting save of zone {1}', session_id,
                         zone_id)
             yield services.get_persistence_service(
             ).save_to_scratch_slot_gen(timeline)
             logger.info('Client {0} save completed for {1}', session_id,
                         zone_id)
             with telemetry_helper.begin_hook(
                     area_telemetry_writer,
                     TELEMETRY_HOOK_ZONE_EXIT,
                     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)
             zone.on_teardown(client)
             if client is None:
                 logger.error(
                     'Client {0} not in client manager from zone {1}',
                     session_id, zone_id)
                 return callback(zone_id, session_id, NO_CLIENT_ERROR_CODE)
             client_manager.remove(client)
         return callback(zone_id, session_id, SUCCESS_CODE)
     except:
         logger.exception('Error disconnecting the client')
         return callback(zone_id, session_id, EXCEPTION_ERROR_CODE)
 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)
예제 #5
0
 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.')
예제 #6
0
 def change_age(self, new_age, current_age):
     self.age_progress = 0
     self.apply_age(new_age)
     self.appearance_tracker.evaluate_appearance_modifiers()
     self.resend_physical_attributes()
     self._update_age_trait(new_age, current_age)
     self.career_tracker.add_ageup_careers()
     self.career_tracker.remove_invalid_careers()
     self.trait_tracker.remove_invalid_traits()
     if self.aspiration_tracker is not None:
         self.aspiration_tracker.remove_invalid_aspirations()
     self.update_skills_for_aging()
     add_quirks(self)
     sim_instance = self.get_sim_instance(
         allow_hidden_flags=ALL_HIDDEN_REASONS)
     if sim_instance is not None:
         with telemetry_helper.begin_hook(writer_age,
                                          TELEMETRY_CHANGE_AGE,
                                          sim=sim_instance) as hook:
             hook.write_enum('agef', current_age)
             hook.write_enum('aget', new_age)
         sim_instance.schedule_element(
             services.time_service().sim_timeline,
             build_element(sim_instance._update_face_and_posture_gen))
         sim_instance._update_multi_motive_buff_trackers()
         sim_instance.update_portal_locks()
         sim_instance.update_rig()
     self.reset_age_progress()
     if not self.is_npc and self.whim_tracker is not None:
         self.whim_tracker.validate_goals()
     client = services.client_manager().get_client_by_household_id(
         self._household_id)
     if client is None:
         return
     client.selectable_sims.notify_dirty()
예제 #7
0
 def _add_interaction(self, interaction_queue, interaction, interaction_id_to_insert_after, queue_type):
     skill = interaction.get_associated_skill()
     (ui_visual_type, visual_group_data) = interaction.get_interaction_queue_visual_type()
     participants = None
     social_group = interaction.social_group
     if social_group is not None:
         participants = list(social_group)
     if not participants:
         participants = interaction.get_participants(ParticipantType.TargetSim | ParticipantType.Listeners)
     int_info = InteractionInfo(interaction.id, interaction.user_facing_target, participants, interaction.is_finishing, interaction.user_cancelable, interaction.get_name(), interaction.get_icon_info(), interaction.context.insert_strategy, skill, ui_visual_type, Sims_pb2.IQ_QUEUED, visual_group_data.group_tag, visual_group_data.group_priority, interaction.priority, interaction.mood_list)
     if not interaction.is_super:
         super_interaction = interaction.super_interaction
         if super_interaction is not None and super_interaction is not interaction:
             int_info.super_id = self._get_super_id_for_mixer(super_interaction.id) or super_interaction.id
             (super_interaction_info, _) = self._find_interaction(int_info.super_id)
             sa_name = super_interaction_info.display_name if super_interaction_info is not None else None
         else:
             sa_name = interaction.super_affordance.get_name(target=interaction.target, context=interaction.context)
         sa_icon_info = interaction.super_affordance.get_icon_info(target=interaction.target, context=interaction.context)
         int_info.set_super_icon_info(sa_name, sa_icon_info)
     if queue_type == self.QueueType.Queue:
         self._add_interaction_info_to_queue(interaction_queue, int_info, interaction, interaction_id_to_insert_after)
     else:
         interaction_queue.append(int_info)
     if interaction.context.source == interactions.context.InteractionSource.PIE_MENU:
         with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_INTERACTION_QUEUE, sim=self._sim) as hook:
             hook.write_guid('idix', interaction.guid64)
             hook.write_int('queu', interaction_queue.index(int_info))
     return int_info
예제 #8
0
 def _save_game_gen(self, timeline, save_game_data, check_cooldown=True):
     save_lock_reason = self.get_save_lock_tooltip()
     if save_lock_reason is not None:
         return (SaveGameResult.FAILED_SAVE_LOCKED, save_lock_reason)
         yield
     current_time = services.server_clock_service().now()
     result_code = SaveGameResult.FAILED_ON_COOLDOWN
     if self._time_of_last_save is not None:
         cooldown = (current_time - self._time_of_last_save).in_real_world_seconds()
     else:
         cooldown = PersistenceTuning.SAVE_GAME_COOLDOWN + 1
     if not check_cooldown or cooldown > PersistenceTuning.SAVE_GAME_COOLDOWN:
         result_code = SaveGameResult.SUCCESS
         error_code_string = None
         try:
             yield from self._fill_and_send_save_game_protobufs_gen(timeline, save_game_data.slot_id, save_game_data.slot_name, auto_save_slot_id=save_game_data.auto_save_slot_id)
         except Exception as e:
             result_code = SaveGameResult.FAILED_EXCEPTION_OCCURRED
             error_code_string = persistence_error_types.generate_exception_code(self.save_error_code, e)
             logger.exception('Save failed due to Exception', exc=e)
             with telemetry_helper.begin_hook(save_telemetry_writer, TELEMETRY_HOOK_SAVE_FAIL) as hook:
                 hook.write_int(TELEMETRY_FIELD_ERROR_CODE, self.save_error_code)
                 hook.write_int(TELEMETRY_FIELD_STACK_HASH, sims4.hash_util.hash64(error_code_string))
         finally:
             self.save_error_code = persistence_error_types.ErrorCodes.NO_ERROR
     if check_cooldown:
         if result_code == SaveGameResult.SUCCESS:
             self._time_of_last_save = current_time
     failure_reason = self._get_failure_reason_for_result_code(result_code, error_code_string)
     return (result_code, failure_reason)
     yield
예제 #9
0
 def _send_gig_telemetry(self, progress):
     with telemetry_helper.begin_hook(gig_telemetry_writer,
                                      TELEMETRY_HOOK_GIG_PROGRESS,
                                      sim_info=self._owner) as hook:
         hook.write_int(TELEMETRY_CAREER_ID, self.career.guid64)
         hook.write_int(TELEMETRY_GIG_ID, self.guid64)
         hook.write_int(TELEMETRY_GIG_PROGRESS_NUMBER, progress)
 def process_action(self, story_progression_flags):
     if FameTunables.FAME_RANKED_STATISTIC is None:
         return
     played_famous = 0
     non_played_famous = 0
     non_played_fame_level = Counter()
     for sim_info in services.sim_info_manager().get_all():
         if sim_info.lod == SimInfoLODLevel.MINIMUM:
             continue
         fame_stat = sim_info.get_statistic(
             FameTunables.FAME_RANKED_STATISTIC)
         if fame_stat.rank_level >= 1:
             if sim_info.is_player_sim:
                 played_famous += 1
             else:
                 non_played_famous += 1
                 non_played_fame_level[fame_stat.rank_level] += 1
     with telemetry_helper.begin_hook(fame_telemetry_writer,
                                      TELEMETRY_HOOK_FAME) as hook:
         hook.write_int(TELEMETRY_FIELD_FAME_PLAYED, played_famous)
         hook.write_int(TELEMETRY_FIELD_FAME_NON_PLAYED, non_played_famous)
         hook.write_int(TELEMETRY_FIELD_FAME_ONE_STAR_NON_PLAYED,
                        non_played_fame_level[1])
         hook.write_int(TELEMETRY_FIELD_FAME_TWO_STAR_NON_PLAYED,
                        non_played_fame_level[2])
         hook.write_int(TELEMETRY_FIELD_FAME_THREE_STAR_NON_PLAYED,
                        non_played_fame_level[3])
         hook.write_int(TELEMETRY_FIELD_FAME_FOUR_STAR_NON_PLAYED,
                        non_played_fame_level[4])
         hook.write_int(TELEMETRY_FIELD_FAME_FIVE_STAR_NON_PLAYED,
                        non_played_fame_level[5])
예제 #11
0
 def _send_business_closed_telemetry(self):
     with telemetry_helper.begin_hook(business_telemetry_writer, TELEMETRY_HOOK_BUSINESS_CLOSED, household=services.household_manager().get(self.owner_household_id)) as hook:
         hook.write_int(TELEMETRY_HOOK_LENGTH_BUSINESS_OPENED, self.minutes_open)
         hook.write_int(TELEMETRY_HOOK_NUM_WORKERS, self.employee_count)
         hook.write_int(TELEMETRY_HOOK_AMOUNT_PROFIT, self.get_daily_net_profit())
         hook.write_float(TELEMETRY_HOOK_STAR_RATING, self.get_star_rating())
         hook.write_enum(TELEMETRY_HOOK_BUSINESS_TYPE, self.business_type)
예제 #12
0
 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 check_collection_complete(self, collection_id):
     collection_data = ObjectCollectionData.get_collection_data(collection_id)
     collection_count = len(collection_data.object_list)
     collected_count = sum(1 for collection in self._collections.values() if collection == collection_id)
     if not collection_count or not collected_count:
         return
     client = services.client_manager().get_client_by_household(self._owner)
     if client is not None and client.active_sim is not None:
         message_owner_info = client.active_sim.sim_info
     else:
         message_owner_info = None
     if collection_data.first_collected_notification is not None and message_owner_info is not None and collected_count == 1:
         dialog = collection_data.first_collected_notification(message_owner_info, None)
         dialog.show_dialog()
     if collection_count == collected_count:
         if client is not None:
             with telemetry_helper.begin_hook(collection_telemetry_writer, TELEMETRY_HOOK_COLLECTION_COMPLETE, household=client.household) as hook:
                 hook.write_int(TELEMETRY_COLLECTION_ID, collection_id)
             _sting = ObjectCollectionData.COLLECTION_COMPLETED_STING(client.active_sim)
             _sting.start()
         if message_owner_info is not None:
             dialog = collection_data.completed_award_notification(message_owner_info, None)
             dialog.show_dialog()
             if collection_data.screen_slam is not None:
                 collection_data.screen_slam.send_screen_slam_message(message_owner_info, collection_data.collection_name)
         lot = services.active_lot()
         if lot is not None:
             lot.create_object_in_hidden_inventory(collection_data.completed_award)
         household = services.household_manager().get(self._owner.id)
         if household is not None:
             household.funds.add(collection_data.completed_award_money, Consts_pb2.TELEMETRY_MONEY_ASPIRATION_REWARD, None)
     elif client is not None:
         _sting = ObjectCollectionData.COLLECTION_COLLECTED_STING(client.active_sim)
         _sting.start()
예제 #14
0
 def try_open_npc_store(self):
     if self.owner_household_id is None:
         self._open_pure_npc_store(services.active_lot().get_premade_status() == PremadeLotStatus.IS_PREMADE)
     elif not self.is_owner_household_active:
         self._open_household_owned_npc_store()
     with telemetry_helper.begin_hook(business_telemetry_writer, TELEMETRY_HOOK_NPC_BUSINESS_VISITED, household=services.household_manager().get(self.owner_household_id)) as hook:
         hook.write_enum(TELEMETRY_HOOK_BUSINESS_TYPE, self.business_type)
 def _create_situation(self, additional_sims_to_bring=()):
     guest_list = self._situation_to_run.get_predefined_guest_list()
     if guest_list is None:
         if self._require_predefined_guest_list:
             return
         host_sim_info = self._get_host(additional_sims_to_bring)
         if host_sim_info is None:
             return
         guest_list = SituationGuestList(invite_only=True, host_sim_id=host_sim_info.id)
     else:
         host_sim_info = self._get_host(additional_sims_to_bring)
         if host_sim_info is None:
             return
     if self._NPC_hosted_situation_player_job is not None:
         guest_list.add_guest_info(SituationGuestInfo.construct_from_purpose(self._receiver_sim_info.id, self._NPC_hosted_situation_player_job, SituationInvitationPurpose.INVITED))
     if self._NPC_host_job is not None:
         guest_list.add_guest_info(SituationGuestInfo.construct_from_purpose(host_sim_info.id, self._NPC_host_job, SituationInvitationPurpose.INVITED))
     if additional_sims_to_bring:
         additional_sims_job = self._chosen_dialog.bring_other_sims.situation_job
         for sim_info in additional_sims_to_bring:
             guest_list.add_guest_info(SituationGuestInfo.construct_from_purpose(sim_info.id, additional_sims_job, SituationInvitationPurpose.INVITED))
     if self._NPC_hosted_situation_use_player_sim_as_filter_requester:
         guest_list.filter_requesting_sim_id = self._receiver_sim_info.id
     services.get_zone_situation_manager().create_situation(self._situation_to_run, guest_list=guest_list, zone_id=self._get_zone_id(), scoring_enabled=self._NPC_hosted_situation_scoring_enabled, user_facing=self._user_facing)
     with telemetry_helper.begin_hook(telemetry_writer, TELEMETRY_HOOK_SITUATION_ACCEPTED, sim_info=self._receiver_sim_info) as hook:
         hook.write_guid(TELEMETRY_SITUATION_TYPE_ID, self._situation_to_run.guid64)
         hook.write_int(TELEMETRY_GUEST_COUNT, len(additional_sims_to_bring))
예제 #16
0
def sell_lot_response(dialog):
    if not dialog.accepted:
        return
    business_manager = services.business_service(
    ).get_business_manager_for_zone()
    current_zone = services.current_zone()
    lot = current_zone.lot
    lot_value = lot.furnished_lot_value
    business_manager.modify_funds(lot_value)
    business_manager.transfer_balance_to_household()
    services.get_zone_manager().clear_lot_ownership(current_zone.id)
    business_tracker = services.business_service(
    ).get_business_tracker_for_household(business_manager.owner_household_id,
                                         business_manager.business_type)
    if business_tracker is None:
        logger.warn(
            'Business tracker is None for household {} for business type {}',
            business_manager.owner_household_id,
            business_manager.business_type)
        return
    business_tracker.remove_owner(current_zone.id)
    current_zone.disown_household_objects()
    with telemetry_helper.begin_hook(
            business_telemetry_writer,
            TELEMETRY_HOOK_BUSINESS_SOLD,
            household=services.household_manager().get(
                business_manager.owner_household_id)) as hook:
        hook.write_enum(TELEMETRY_HOOK_BUSINESS_TYPE,
                        business_manager.business_type)
    msg = InteractionOps_pb2.SellRetailLot()
    msg.retail_zone_id = current_zone.id
    distributor.system.Distributor.instance().add_event(
        Consts_pb2.MSG_SELL_RETAIL_LOT, msg)
예제 #17
0
 def _send_invalid_objects_telemetry(self, total_objects, top5_obj_id,
                                     top5_obj_count):
     with telemetry_helper.begin_hook(
             zone_telemetry_writer, TELEMETRY_HOOK_INVALID_OBJECTS) as hook:
         hook.write_int(TELEMETRY_FIELD_OBJECTS_COUNT, total_objects)
         hook.write_string(TELEMETRY_FIELD_TOP5_OBJ_ID, top5_obj_id)
         hook.write_string(TELEMETRY_FIELD_TOP5_OBJ_COUNT, top5_obj_count)
예제 #18
0
 def remove_queued_interaction(self, interaction):
     if not interaction.visible:
         return
     for (index, cur_info) in enumerate(self._queued_interactions):
         while interaction.id == cur_info.interaction_id:
             logger.debug('SimId:{}, Interaction Remove(from queue) is being removed from queued list:{}', self._sim.id, interaction)
             if interaction.user_canceled:
                 with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_INTERACTION_CANCEL, sim=self._sim) as hook:
                     hook.write_int('idit', interaction.id)
                     hook.write_int('queu', index)
             int_info = self._queued_interactions.pop(index)
             interaction_messages.send_interactions_remove_msg(self._sim, (int_info,), int_info.ui_state == Sims_pb2.IQ_QUEUED)
             return
     for int_info in self._running_interactions:
         while interaction.id == int_info.interaction_id and int_info.ui_state == Sims_pb2.IQ_TRANSITIONING:
             previous_visible_group_info_id = self._get_visible_grouped_interaction_id(int_info.interaction_id)
             group_interactions = self._remove_running_interactions(int_info)
             self._remove_routing_interaction_info(int_info)
             if group_interactions:
                 new_visible_interaction_info = group_interactions.pop()
                 if previous_visible_group_info_id == new_visible_interaction_info.interaction_id:
                     return
                 if new_visible_interaction_info.ui_state == Sims_pb2.IQ_RUNNING:
                     interaction_messages.send_interaction_replace_message(self._sim, int_info.interaction_id, new_visible_interaction_info, self._should_msg_be_immediate(self.QueueType.Super))
                 else:
                     interaction_messages.send_interactions_add_msg(self._sim, (new_visible_interaction_info,), self._should_msg_be_immediate(self.QueueType.Super))
             else:
                 interaction_messages.send_interactions_remove_msg(self._sim, (int_info,), immediate=interaction.collapsible)
             return
     for (index, cur_info) in enumerate(self._continuation_interactions):
         while interaction.id == cur_info.interaction_id:
             logger.debug('SimId:{}, Interaction Remove(from queue) is being removed from continuation list:{}', self._sim.id, interaction)
             self._continuation_interactions.pop(index)
             return
     logger.debug('Interaction Remove(from Queue) requested on an interaction not in the ui_manager:{}', interaction)
 def run_death_behavior(self, death_object_data=None, from_reset=False):
     if self._death_object_data is not None:
         return
     if death_object_data is None:
         death_element = self.death_element(self)
         death_object_data = (death_element.create_object(),
                              death_element.placement_failed)
     self._death_object_data = death_object_data
     self.sim.sim_info.career_tracker.on_death()
     self.sim.inventory_component.push_items_to_household_inventory()
     with telemetry_helper.begin_hook(death_telemetry_writer,
                                      TELEMETRY_HOOK_SIM_DIES,
                                      sim=self.sim.sim_info) as hook:
         hook.write_int(TELEMETRY_DEATH_TYPE, self.death_type)
     for si in list(self.sim.interaction_refs):
         si.refresh_conditional_actions()
         si.set_target(None)
         si.remove_liability(RESERVATION_LIABILITY)
     self.sim.remove_from_client()
     self._removed_sim = self.sim
     self._client = self.sim.client
     if from_reset:
         self._finalize_death()
         self.sim.schedule_destroy_asap(source=self.sim,
                                        cause='Sim reset during death.')
     else:
         self.add_exit_function(self.run_post_death_behavior)
예제 #20
0
 def _handle_level_up_telemetry(self, level):
     if not self._suppress_level_up_telemetry:
         with telemetry_helper.begin_hook(
                 ranked_stat_telemetry_writer,
                 TELEMETRY_HOOK_RANKED_STAT_LEVEL_UP) as hook:
             hook.write_guid(TELEMETRY_FIELD_RANKED_STAT_TYPE, self.guid64)
             hook.write_int(TELEMETRY_FIELD_RANKED_STAT_LEVEL, level)
예제 #21
0
 def set_active_sim_info(self, sim_info):
     with telemetry_helper.begin_hook(writer,
                                      TELEMETRY_HOOK_ACTIVE_SIM_CHANGED,
                                      sim_info=sim_info):
         pass
     self.active_sim_info = sim_info
     return self._active_sim_info is not None
 def _run(self):
     zone_id = self._get_zone_id()
     with telemetry_helper.begin_hook(telemetry_writer, TELEMETRY_HOOK_SITUATION_INVITED, sim_info=self._receiver_sim_info) as hook:
         hook.write_guid(TELEMETRY_SITUATION_TYPE_ID, self._situation_to_run.guid64)
         hook.write_int(TELEMETRY_CHOSEN_ZONE, zone_id)
     additional_tokens = []
     if zone_id == 0:
         logger.error('Drama Node {} trying to be run with zone id of 0.  This is probably an issue with getting the zone id from the street.', self)
         zone_id = services.current_zone_id()
     venue_tuning_id = build_buy.get_current_venue(zone_id)
     if venue_tuning_id is not None:
         venue_manager = services.get_instance_manager(sims4.resources.Types.VENUE)
         venue_tuning = venue_manager.get(venue_tuning_id)
         if venue_tuning is not None:
             additional_tokens.append(venue_tuning.display_name)
     persistence_service = services.get_persistence_service()
     zone_data = persistence_service.get_zone_proto_buff(zone_id)
     if zone_data is not None:
         additional_tokens.append(zone_data.name)
     self._choose_dialog()
     dialog = self._chosen_dialog(self._receiver_sim_info, target_sim_id=self._sender_sim_info.id, resolver=self._get_resolver())
     if self._chosen_dialog is None:
         return DramaNodeRunOutcome.FAILURE
     dialog_zone_id = zone_id if self._show_venue_dialog else None
     dialog.show_dialog(on_response=self._handle_dialog, zone_id=dialog_zone_id, additional_tokens=additional_tokens)
     return DramaNodeRunOutcome.SUCCESS_NODE_INCOMPLETE
예제 #23
0
    def _do_behavior(self, *args, **kwargs):
        actors = self.interaction.get_participants(self.travel_group_participant)
        targets = self.interaction.get_participants(self.target_to_add)
        if not (actors and targets):
            logger.error('TravelGroupAdd could not acquire participants.')
            return

        def get_first_travel_group(participants):
            travel_group = None
            for participant in participants:
                travel_group = participant.travel_group
                if travel_group is not None:
                    break
            return travel_group

        travel_group = get_first_travel_group(actors)
        if travel_group is None:
            logger.error('Participant {} does not belong to a travel group.', actors)
            return
        target_travel_group = get_first_travel_group(targets)
        if target_travel_group is not None:
            logger.error('Target {} already belongs to a travel group.', targets)
            return
        for target in targets:
            target_sim_info = services.sim_info_manager().get(target.sim_id)
            if not travel_group.can_add_to_travel_group(target_sim_info):
                logger.error('Cannot add Target {} to Travel Group {}.', target, travel_group)
                return
            travel_group.add_sim_info(target_sim_info)
        with telemetry_helper.begin_hook(travel_group_telemetry_writer, TELEMETRY_HOOK_TRAVEL_GROUP_ADD, sim_info=target_sim_info) as hook:
            hook.write_int(TELEMETRY_TRAVEL_GROUP_ID, travel_group.id)
            hook.write_int(TELEMETRY_TRAVEL_GROUP_ZONE_ID, travel_group.zone_id)
            hook.write_int(TELEMETRY_TRAVEL_GROUP_SIZE, len(travel_group))
            hook.write_int(TELEMETRY_TRAVEL_GROUP_DURATION, int(travel_group.duration_time_span.in_minutes()))
예제 #24
0
 def add(self, amount, reason, sim, tags=None, count_as_earnings=True):
     amount = round(amount)
     if amount < 0:
         logger.error('Attempt to add negative amount of money to Family Funds.', owner='mduke')
         return
     if sim is None:
         for client in services.client_manager().objects:
             while client.household_id == self._household.id:
                 self._update_money(amount, reason, client.account.id, tags=tags, count_as_earnings=count_as_earnings)
                 return
         logger.callstack('Attempt to raise household funds on a house with no client connected.', owner='nbaker', level=sims4.log.LEVEL_WARN)
     else:
         if sim.household != self._household:
             logger.error('Attempt to add funds to the wrong household.', owner='mduke')
             return
         status = sim.account_connection
         if status == AccountConnection.OFFLINE:
             return
         if status == AccountConnection.DIFFERENT_LOT:
             sim.sim_info.add_to_personal_funds(amount)
             with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_POCKET, sim=sim) as hook:
                 hook.write_int(TELEMETRY_AMOUNT, amount)
                 hook.write_int(TELEMETRY_REASON, reason)
         else:
             self._update_money(amount, reason, sim.account_id, sim, tags=tags, count_as_earnings=count_as_earnings)
예제 #25
0
def log_interaction(phase, interaction, msg=None):
    if interaction.is_super:
        progress = str(interaction.pipeline_progress).split('.', 1)[-1]
    else:
        progress = ''
    source = str(interaction.context.source).split('.', 1)[-1]
    priority = str(interaction.priority).split('.', 1)[-1]
    sim_name = _get_sim_name(interaction.sim)
    interaction_name = getattr(interaction, 'name_override', interaction.affordance.__name__)
    interaction_name = '{}({})'.format(interaction_name, interaction.id)
    logger.info(_INTERACTION_LOG_FORMAT.format(phase=phase, name=interaction_name, sim=sim_name, target=_get_object_name(interaction.target), progress=progress, context='{}-{}'.format(source, priority), msg=_get_csv_friendly_string(msg) or ''))
    if archiver.enabled:
        archive_data = {'affordance': interaction_name, 'phase': phase, 'target': str(interaction.target), 'context': '{}, {}'.format(source, priority), 'progress': progress}
        if msg:
            archive_data['message'] = msg
        archiver.archive(data=archive_data, object_id=interaction.sim.id if interaction.sim is not None else 0)
    if interaction.sim is not None and interaction.sim.interaction_logging:
        log_queue_automation(interaction.sim)
    hook_tag = TELEMETRY_HOOK_MAPPING.get((phase, interaction.is_super))
    if hook_tag is not None and interaction.visible:
        with telemetry_helper.begin_hook(writer, hook_tag, sim=interaction.sim) as hook:
            hook.write_guid(TELEMETRY_FIELD_INTERACTION_ID, interaction.guid64)
            hook.write_int(TELEMETRY_FIELD_SOURCE, interaction.source)
            hook.write_int(TELEMETRY_FIELD_GROUP_ID, interaction.group_id)
            target = interaction.target
            if target is not None:
                hook.write_int(TELEMETRY_FIELD_TARGET_ID, target.id)
                hook.write_int(TELEMETRY_FIELD_TARGET_TYPE, target.definition.id)
            outcome_result = interaction.outcome_result
            while outcome_result is not None:
                hook.write_int(TELEMETRY_FIELD_OUTCOME, interaction.outcome_result)
예제 #26
0
 def request_client_disconnect_gen(timeline):
     try:
         zone = services.current_zone()
         if zone is not None:
             client_manager = services.client_manager()
             client = client_manager.get(session_id)
             logger.info('Client {0} starting save of zone {1}', session_id,
                         zone_id)
             yield from services.get_persistence_service(
             ).save_to_scratch_slot_gen(timeline)
             logger.info('Client {0} save completed for {1}', session_id,
                         zone_id)
             with telemetry_helper.begin_hook(
                     area_telemetry_writer,
                     TELEMETRY_HOOK_ZONE_EXIT,
                     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)
             zone.on_teardown(client)
             if client is None:
                 logger.error(
                     'Client {0} not in client manager from zone {1}',
                     session_id, zone_id)
                 return callback(zone_id, session_id, NO_CLIENT_ERROR_CODE)
                 yield
             client_manager.remove(client)
         return callback(zone_id, session_id, SUCCESS_CODE)
         yield
     except:
         logger.exception('Error disconnecting the client')
         return callback(zone_id, session_id, EXCEPTION_ERROR_CODE)
         yield
예제 #27
0
 def destroy_travel_group_and_release_zone(self,
                                           travel_group,
                                           last_sim_info=None,
                                           return_objects=False):
     if travel_group.played:
         if last_sim_info is None:
             leader_sim_info = services.active_sim_info()
             if leader_sim_info not in travel_group:
                 leader_sim_info = next(iter(travel_group), None)
         else:
             leader_sim_info = last_sim_info
         with telemetry_helper.begin_hook(travel_group_telemetry_writer,
                                          TELEMETRY_HOOK_TRAVEL_GROUP_END,
                                          sim_info=leader_sim_info) as hook:
             hook.write_int(TELEMETRY_TRAVEL_GROUP_ID, travel_group.id)
             hook.write_int(TELEMETRY_TRAVEL_GROUP_ZONE_ID,
                            travel_group.zone_id)
             hook.write_int(TELEMETRY_TRAVEL_GROUP_SIZE, len(travel_group))
             hook.write_int(
                 TELEMETRY_TRAVEL_GROUP_DURATION,
                 int(travel_group.duration_time_span.in_minutes()))
     for sim_info in tuple(travel_group):
         travel_group.remove_sim_info(sim_info, destroy_on_empty=False)
     self.release_zone(travel_group.zone_id)
     services.get_persistence_service().del_travel_group_proto_buff(
         travel_group.id)
     services.travel_group_manager().remove(travel_group)
     if return_objects:
         self.return_objects_left_in_destination_world()
     return True
예제 #28
0
 def send_startup_telemetry_event(self):
     with telemetry_helper.begin_hook(
             career_zone_director_telemetry_writer,
             TELEMETRY_HOOK_ZONE_DIRECTOR_START,
             sim_info=self._career_event.sim_info) as hook:
         hook.write_guid(TELEMETRY_CAREER_ID,
                         self._career_event.career.guid64)
     self._start_time = services.time_service().sim_now
예제 #29
0
 def _send_telemetry_event_for_bit_change(self, telemetry_hook, bit,
                                          sim_info, target_sim_info):
     with telemetry_helper.begin_hook(writer,
                                      telemetry_hook,
                                      sim_info=sim_info) as hook:
         hook.write_int(TELEMETRY_FIELD_TARGET_ID, target_sim_info.sim_id)
         hook.write_int(TELEMETRY_FIELD_REL_ID, target_sim_info.sim_id)
         hook.write_int(TELEMETRY_FIELD_BIT_ID, bit.guid64)
 def _handle_picker_dialog(self, dialog):
     if not dialog.accepted:
         with telemetry_helper.begin_hook(telemetry_writer, TELEMETRY_HOOK_SITUATION_REJECTED, sim_info=self._receiver_sim_info) as hook:
             hook.write_guid('type', self._situation_to_run.guid64)
     else:
         picked_sims = dialog.get_result_tags()
         self._create_situation(additional_sims_to_bring=picked_sims)
     services.drama_scheduler_service().complete_node(self.uid)
예제 #31
0
 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()
예제 #32
0
 def remove_queued_interaction(self, interaction):
     if not interaction.visible:
         return
     for (index, cur_info) in enumerate(self._queued_interactions):
         while interaction.id == cur_info.interaction_id:
             logger.debug(
                 'SimId:{}, Interaction Remove(from queue) is being removed from queued list:{}',
                 self._sim.id, interaction)
             if interaction.user_canceled:
                 with telemetry_helper.begin_hook(
                         writer,
                         TELEMETRY_HOOK_INTERACTION_CANCEL,
                         sim=self._sim) as hook:
                     hook.write_int('idit', interaction.id)
                     hook.write_int('queu', index)
             int_info = self._queued_interactions.pop(index)
             interaction_messages.send_interactions_remove_msg(
                 self._sim, (int_info, ),
                 int_info.ui_state == Sims_pb2.IQ_QUEUED)
             return
     for int_info in self._running_interactions:
         while interaction.id == int_info.interaction_id and int_info.ui_state == Sims_pb2.IQ_TRANSITIONING:
             previous_visible_group_info_id = self._get_visible_grouped_interaction_id(
                 int_info.interaction_id)
             group_interactions = self._remove_running_interactions(
                 int_info)
             self._remove_routing_interaction_info(int_info)
             if group_interactions:
                 new_visible_interaction_info = group_interactions.pop()
                 if previous_visible_group_info_id == new_visible_interaction_info.interaction_id:
                     return
                 if new_visible_interaction_info.ui_state == Sims_pb2.IQ_RUNNING:
                     interaction_messages.send_interaction_replace_message(
                         self._sim, int_info.interaction_id,
                         new_visible_interaction_info,
                         self._should_msg_be_immediate(
                             self.QueueType.Super))
                 else:
                     interaction_messages.send_interactions_add_msg(
                         self._sim, (new_visible_interaction_info, ),
                         self._should_msg_be_immediate(
                             self.QueueType.Super))
             else:
                 interaction_messages.send_interactions_remove_msg(
                     self._sim, (int_info, ),
                     immediate=interaction.collapsible)
             return
     for (index, cur_info) in enumerate(self._continuation_interactions):
         while interaction.id == cur_info.interaction_id:
             logger.debug(
                 'SimId:{}, Interaction Remove(from queue) is being removed from continuation list:{}',
                 self._sim.id, interaction)
             self._continuation_interactions.pop(index)
             return
     logger.debug(
         'Interaction Remove(from Queue) requested on an interaction not in the ui_manager:{}',
         interaction)
def send_eco_footprint_state_change_telemetry(world_description_id, old_state,
                                              new_state, convergence_value):
    with telemetry_helper.begin_hook(
            _telemetry_writer,
            TELEMETRY_HOOK_ECO_FOOTPRINT_STATE_CHANGE) as hook:
        hook.write_guid(TELEMETRY_FIELD_NEIGHBORHOOD, world_description_id)
        hook.write_enum(TELEMETRY_FIELD_OLD_FOOTPRINT_STATE, old_state)
        hook.write_enum(TELEMETRY_FIELD_NEW_FOOTPRINT_STATE, new_state)
        hook.write_float(TELEMETRY_FIELD_CONVERGENCE_VALUE, convergence_value)
예제 #34
0
 def send_detective_telemetry(self, hook_tag):
     with telemetry_helper.begin_hook(detective_telemetry_writer,
                                      hook_tag,
                                      sim_info=self.sim_info) as hook:
         hook.write_int(TELEMETRY_DETECTIVE_CRIMINAL_ID,
                        self.active_criminal_sim_id)
         if hook_tag == TELEMETRY_HOOK_DETECTIVE_CASE_END and self._case_start_time_in_minutes != 0:
             now = int(services.time_service().sim_now.absolute_minutes())
             duration = now - self._case_start_time_in_minutes
             hook.write_int(TELEMETRY_DETECTIVE_CRIME_DURATION, duration)
예제 #35
0
 def _handle_perk_lock_telemetry(self, perk):
     new_bucks_total = self.get_bucks_amount_for_type(
         perk.associated_bucks_type)
     with telemetry_helper.begin_hook(perks_telemetry_writer,
                                      TELEMETRY_HOOK_PERKS_REFUND) as hook:
         hook.write_int(TELEMETRY_FIELD_BUCKS_TYPE,
                        perk.associated_bucks_type)
         hook.write_int(TELEMETRY_FIELD_BUCKS_AMOUNT, perk.unlock_cost)
         hook.write_int(TELEMETRY_FIELD_BUCKS_TOTAL, new_bucks_total)
         hook.write_guid(TELEMETRY_FIELD_BUCKS_SOURCE, perk.guid64)
def report_game_clock_is_behind(current_game_speed, ticks_behind):
    global g_num_times_game_clock_fell_behind_telemetry_sent
    if g_num_times_game_clock_fell_behind_telemetry_sent < MAX_TELEMETRY_FOR_GAME_CLOCK_BEHIND:
        with telemetry_helper.begin_hook(
                clock_telemetry_writer,
                TELEMETRY_HOOK_GAME_CLOCK_BEHIND) as hook:
            hook.write_int(TELEMETRY_FIELD_TIME_DIFF, ticks_behind)
            hook.write_int(TELEMETRY_FIELD_CURRENT_CLOCK_SPEED,
                           int(current_game_speed))
            g_num_times_game_clock_fell_behind_telemetry_sent += 1
예제 #37
0
 def release(self):
     for (tracker, handle) in self._handles.items():
         tracker.remove_watcher(handle)
     self.send_quality_update(liabilty_release=True)
     self._crafting_process._current_crafting_interaction = None
     sim = self._crafting_process.crafter
     if sim is not None:
         with telemetry_helper.begin_hook(crafting_telemetry_writer, TELEMETRY_HOOK_CRAFTING_END, sim=sim.sim_info) as hook:
             hook.write_localized_string(TELEMETRY_FIELD_RECIPE_NAME, self._crafting_process.recipe.get_recipe_name(sim))
             hook.write_int(TELEMETRY_FIELD_RECIPE_QUALITY, self._crafting_process.crafting_quality)
             hook.write_bool(TELEMETRY_FIELD_RECIPE_COMPLETE, self._crafting_process.is_complete)
예제 #38
0
 def on_skill_updated(self, telemhook, old_value, new_value, affordance_name):
     owner_sim = self._tracker._owner
     if owner_sim.is_selectable:
         with telemetry_helper.begin_hook(skill_telemetry_writer, telemhook, sim=owner_sim) as hook:
             hook.write_guid(TELEMETRY_FIELD_SKILL_ID, self.guid64)
             hook.write_string(TELEMETRY_FIELD_SKILL_AFFORDANCE, affordance_name)
             hook.write_bool(TELEMETRY_FIELD_SKILL_AFFORDANCE_SUCCESS, True)
             hook.write_int(TELEMETRY_FIELD_SKILL_AFFORDANCE_VALUE_ADD, new_value - old_value)
     if old_value == self.initial_value:
         skill_level = self.convert_to_user_value(old_value)
         self._show_level_notification(skill_level)
예제 #39
0
 def _remove_whim_goal(self, whim_goal, whim_goal_set):
     with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_WHIM_EVENT, sim=self._sim_info) as hook:
         hook.write_int(TELEMETRY_WHIM_EVENT_TYPE, TelemetryWhimEvents.CANCELED)
         hook.write_guid(TELEMETRY_WHIM_GUID, whim_goal.guid64)
     self.deactivate_set(whim_goal_set, from_cancel=True)
     whim_goal.unregister_for_on_goal_completed_callback(self._on_goal_completed)
     self._remove_goal_from_current_order(whim_goal)
     if __debug__ and whim_goal.__class__ in self._test_results_map:
         del self._test_results_map[whim_goal.__class__]
     if whim_goal in self._realized_goals:
         del self._realized_goals[whim_goal]
     whim_goal.decommision()
예제 #40
0
 def __init__(self, crafting_process, created_by=None):
     self._crafting_process = crafting_process
     self._created_by = created_by
     self._handles = {}
     for stat_type in self.CRAFTING_STATISTICS:
         tracker = crafting_process.get_tracker(stat_type)
         while tracker not in self._handles:
             self._handles[tracker] = tracker.add_watcher(self._on_stat_change)
     sim = self._crafting_process.crafter
     if sim is not None:
         with telemetry_helper.begin_hook(crafting_telemetry_writer, TELEMETRY_HOOK_CRAFTING_START, sim=sim.sim_info) as hook:
             hook.write_localized_string(TELEMETRY_FIELD_RECIPE_NAME, self._crafting_process.recipe.get_recipe_name(sim))
예제 #41
0
 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)
예제 #42
0
 def offer_goals(self, debug_goal=None, debug_target=None, request_single_goal=False, emotion_only=False):
     if not self.emotion_whim_needed and self.whims_needed == 0:
         return
     if self._sim_info.is_npc:
         return
     if self._sim is None:
         return
     chosen_tuned_goals = {}
     if self.whims_needed > 0:
         normal_whimset_list = services.get_instance_manager(sims4.resources.Types.ASPIRATION).normal_whim_sets
         prioritized_tuned_whim_sets = []
         for whim_set in normal_whimset_list:
             priority = self.get_priority(whim_set)
             while priority != 0:
                 prioritized_tuned_whim_sets.append((priority, whim_set))
         if not emotion_only:
             self._select_goals(prioritized_tuned_whim_sets, chosen_tuned_goals, debug_goal, debug_target, request_single_goal)
     if self.emotion_whim_needed:
         emotion_whimset_list = services.get_instance_manager(sims4.resources.Types.ASPIRATION).emotion_whim_sets
         prioritized_tuned_whim_sets = []
         for whim_set in emotion_whimset_list:
             priority = self.get_priority(whim_set)
             while priority != 0 and whim_set.whimset_emotion is self._sim_mood:
                 prioritized_tuned_whim_sets.append((priority, whim_set))
         self._select_goals(prioritized_tuned_whim_sets, chosen_tuned_goals, debug_goal, debug_target)
     if self._goals_dirty:
         index = 0
         for tuned_goal in chosen_tuned_goals:
             goal_added = False
             if chosen_tuned_goals[tuned_goal].whimset_emotion is not None:
                 goal = tuned_goal(sim_info=self._sim_info, goal_id=self._goal_id_generator(), inherited_target_sim_info=self._whimset_target_map[chosen_tuned_goals[tuned_goal]])
                 self._active_whims[WhimsTracker.MAX_GOALS] = goal
                 goal_added = True
             else:
                 while index < WhimsTracker.MAX_GOALS:
                     if self._active_whims[index] is None:
                         goal = tuned_goal(sim_info=self._sim_info, goal_id=self._goal_id_generator(), inherited_target_sim_info=self._whimset_target_map[chosen_tuned_goals[tuned_goal]])
                         self._active_whims[index] = goal
                         goal_added = True
                         break
                     index += 1
             if goal_added:
                 self._realized_goals[goal] = chosen_tuned_goals[tuned_goal]
                 goal.register_for_on_goal_completed_callback(self._on_goal_completed)
                 logger.debug('Added whim for {}: {}', self._sim_info, goal, owner='jjacobson')
             else:
                 logger.error('Trying to add a whim when the active whims are already full.', owner='jjacobson.')
             with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_WHIM_EVENT, sim=self._sim_info) as hook:
                 hook.write_int(TELEMETRY_WHIM_EVENT_TYPE, TelemetryWhimEvents.ADDED)
                 hook.write_guid(TELEMETRY_WHIM_GUID, goal.guid64)
     if len(self._realized_goals) > WhimsTracker.MAX_GOALS + 1:
         logger.error('Too many whims active.  Current Whims: {}', self._realized_goals.keys(), owner='jjacobson')
예제 #43
0
 def add_trait(self, trait):
     if not self.can_add_trait(trait):
         return False
     self._equipped_traits.add(trait)
     self._add_buffs(trait)
     self._sim_info.resend_trait_ids()
     sim = self._sim_info.get_sim_instance()
     if sim is not None:
         with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_ADD_TRAIT, sim=sim) as hook:
             hook.write_int(TELEMETRY_FIELD_TRAIT_ID, trait.guid64)
         services.social_service.post_trait_message(self._sim_info, trait, added=True)
         services.get_event_manager().process_event(test_events.TestEvent.TraitAddEvent, sim_info=self._sim_info)
     return True
예제 #44
0
 def remove_trait(self, trait):
     if not self.has_trait(trait):
         logger.warn('Try to remove a non-equipped trait {}', trait)
         return False
     self._equipped_traits.remove(trait)
     self._remove_buffs(trait)
     self._sim_info.resend_trait_ids()
     sim = self._sim_info.get_sim_instance()
     if sim is not None:
         with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_REMOVE_TRAIT, sim=sim) as hook:
             hook.write_int(TELEMETRY_FIELD_TRAIT_ID, trait.guid64)
         services.social_service.post_trait_message(self._sim_info, trait, added=False)
     return True
예제 #45
0
 def _dismiss_emotion_whim(self):
     if len(self._active_whims) != 0:
         emotion_whim = self._active_whims[WhimsTracker.MAX_GOALS]
         if emotion_whim is not None:
             whimset = self._realized_goals[emotion_whim]
             if whimset.whimset_emotion is not self._sim_mood:
                 emotion_guid64 = emotion_whim.guid64
                 with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_WHIM_EVENT, sim=self._sim_info) as hook:
                     hook.write_int(TELEMETRY_WHIM_EVENT_TYPE, TelemetryWhimEvents.NO_LONGER_AVAILABLE)
                     hook.write_guid(TELEMETRY_WHIM_GUID, emotion_guid64)
                 self.dismiss_whim(emotion_guid64)
                 return
         self._goals_dirty = True
         self._send_goals_update()
예제 #46
0
 def on_skill_level_up(self, old_level, new_level):
     tracker = self.tracker
     sim_info = tracker._owner
     if self.reached_max_level:
         for skill in self.skill_unlocks_on_max:
             skill_instance = tracker.add_statistic(skill, force_add=True)
             skill_instance.set_value(skill.initial_value)
     with telemetry_helper.begin_hook(skill_telemetry_writer, TELEMETRY_HOOK_SKILL_LEVEL_UP, sim=sim_info) as hook:
         hook.write_guid(TELEMETRY_FIELD_SKILL_ID, self.guid64)
         hook.write_int(TELEMETRY_FIELD_SKILL_LEVEL, new_level)
     if sim_info.account is not None:
         services.social_service.post_skill_message(sim_info, self, old_level, new_level)
     self._show_level_notification(new_level)
     services.get_event_manager().process_event(test_events.TestEvent.SkillLevelChange, sim_info=sim_info, statistic=self.stat_type)
예제 #47
0
 def quit_career(self, post_quit_msg=True):
     with telemetry_helper.begin_hook(career_telemetry_writer, TELEMETRY_HOOK_CAREER_END, 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, self._level)
     loot = self.current_level_tuning.loot_on_quit
     if loot is not None:
         resolver = SingleSimResolver(self._sim_info)
         loot.apply_to_resolver(resolver)
     self._sim_info.career_tracker.career_leave(self)
     if post_quit_msg:
         self.send_career_message(self.career_messages.quit_career_notification)
     self.resend_career_data()
     self.resend_at_work_info()
예제 #48
0
 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)
예제 #49
0
 def demote(self, auto_fire=False):
     if random.random() < self.demotion_chance_modifiers.get_multiplier(SingleSimResolver(self._sim_info)):
         demote_fired = False
         if self.can_be_fired and (auto_fire or self._level - 1 < 0):
             demote_fired = True
             self.send_career_message(self.career_messages.fire_career_notification)
             self._sim_info.career_tracker.remove_career(self.guid64, post_quit_msg=False)
         elif self._change_level(-1):
             self.send_career_message(self.career_messages.demote_career_notification)
         if demote_fired:
             if self.fired_buff is not None:
                 self._sim_info.add_buff_from_op(self.fired_buff.buff_type, buff_reason=self.fired_buff.buff_reason)
         elif self.demotion_buff is not None:
             self._sim_info.add_buff_from_op(self.demotion_buff.buff_type, buff_reason=self.demotion_buff.buff_reason)
         curr_level = -1 if demote_fired else self._level
         with telemetry_helper.begin_hook(career_telemetry_writer, TELEMETRY_HOOK_CAREER_DEMOTION, 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, curr_level)
예제 #50
0
 def collect_rewards(self, time_at_work):
     current_level_tuning = self.current_level_tuning
     performance_metrics = current_level_tuning.performance_metrics
     work_duration = self._current_work_duration.in_hours()
     percent_at_work = time_at_work/work_duration
     work_time_multiplier = 1
     if percent_at_work*100 < performance_metrics.full_work_day_percent:
         self.work_performance_stat.add_value(-performance_metrics.missed_work_penalty)
         work_time_multiplier = percent_at_work/(performance_metrics.full_work_day_percent/100)
     work_money = math.ceil(self.get_hourly_pay()*work_duration*work_time_multiplier)
     self._sim_info.household.funds.add(work_money, Consts_pb2.TELEMETRY_MONEY_CAREER, self._get_sim())
     with telemetry_helper.begin_hook(career_telemetry_writer, TELEMETRY_HOOK_CAREER_DAILY_END, 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, self._level)
     if self.attended_work:
         self.send_career_message(self.career_messages.career_daily_end_notification, work_money)
     if self.evaluate_career_performance() or self.career_messages.career_performance_warning.threshold.compare(self.work_performance):
         self.send_career_message(self.career_messages.career_performance_warning.dialog, on_response=self._career_performance_warning_response)
     return work_money
예제 #51
0
 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)
예제 #52
0
 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()
예제 #53
0
 def _handle_promotion(self):
     self._pending_promotion = True
     previous_level_tuning = self.current_level_tuning
     previous_salary = self.get_hourly_pay()
     previous_highest_level = self._sim_info.career_tracker.get_highest_level_reached(self.guid64)
     try:
         yield None
     finally:
         if self.current_level_tuning is not previous_level_tuning:
             self._pending_promotion = False
             if self.user_level > previous_highest_level and self.current_level_tuning.promotion_reward is not None:
                 reward_payout = self.current_level_tuning.promotion_reward.give_reward(self._sim_info)
                 reward_text = LocalizationHelperTuning.get_bulleted_list(None, *(reward.get_display_text() for reward in reward_payout))
             else:
                 reward_text = None
             (_, next_work_time, _) = self.get_next_work_time()
             salary = self.get_hourly_pay()
             salary_increase = salary - previous_salary
             level_text = self.current_level_tuning.promotion_notification_text(self._sim_info)
             is_not_school = not self.get_is_school()
             if reward_text is None:
                 self.send_career_message(self.career_messages.promote_career_rewardless_notification, next_work_time, salary, salary_increase, level_text, display_career_info=is_not_school)
             else:
                 self.send_career_message(self.career_messages.promote_career_notification, next_work_time, salary, salary_increase, level_text, reward_text, display_career_info=is_not_school)
             promotion_sting = self.current_level_tuning.promotion_audio_sting
             if promotion_sting is not None:
                 play_tunable_audio(promotion_sting)
             if self.current_level_tuning.screen_slam is not None:
                 self.current_level_tuning.screen_slam.send_screen_slam_message(self._sim_info, self._sim_info, self.current_level_tuning.title(self._sim_info), self.user_level, self.current_track_tuning.career_name(self._sim_info))
             if self.has_outfit():
                 self._sim_info.refresh_current_outfit()
             else:
                 new_outfit = self._sim_info._outfits.get_outfit_for_clothing_change(None, OutfitChangeReason.DefaultOutfit, resolver=SingleSimResolver(self._sim_info))
                 self._sim_info.set_current_outfit(new_outfit)
             with telemetry_helper.begin_hook(career_telemetry_writer, TELEMETRY_HOOK_CAREER_PROMOTION, 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, self._level)
예제 #54
0
 def on_client_disconnect(self, client):
     self._update_time_spent_in_speed(self.clock_speed())
     total_time_spent = services.server_clock_service().ticks(
     ) - self._initial_server_ticks
     for speed in ClockSpeedMode:
         time_spent_in_speed = self._server_ticks_spent_in_speed[speed]
         precentage_time_in_speed = time_spent_in_speed / float(
             total_time_spent) * 100
         time_spent_in_speed = time_spent_in_speed / date_and_time.TICKS_PER_REAL_WORLD_SECOND
         with telemetry_helper.begin_hook(
                 clock_telemetry_writer,
                 TELEMETRY_HOOK_CHANGE_SPEED_REPORT,
                 household=client.household) as hook:
             hook.write_int(TELEMETRY_FIELD_CLOCK_SPEED, speed)
             hook.write_int(TELEMETRY_FIELD_TIME_SPENT_IN_SPEED,
                            time_spent_in_speed)
             hook.write_float(
                 TELEMETRY_FIELD_PERCENTAGE_TIME_SPENT_IN_SPEED,
                 precentage_time_in_speed)
     if GameClock._is_single_player():
         self.set_clock_speed(ClockSpeedMode.PAUSED)
         self._time_of_last_save = self.now()
 def run_death_behavior(self, death_object_data=None, from_reset=False):
     if self._death_object_data is not None:
         return
     if death_object_data is None:
         death_element = self.death_element(self)
         death_object_data = (death_element.create_object(), death_element.placement_failed)
     self._death_object_data = death_object_data
     self.sim.sim_info.career_tracker.on_death()
     self.sim.inventory_component.push_items_to_household_inventory()
     with telemetry_helper.begin_hook(death_telemetry_writer, TELEMETRY_HOOK_SIM_DIES, sim=self.sim.sim_info) as hook:
         hook.write_int(TELEMETRY_DEATH_TYPE, self.death_type)
     for si in list(self.sim.interaction_refs):
         si.refresh_conditional_actions()
         si.set_target(None)
         si.remove_liability(RESERVATION_LIABILITY)
     self.sim.remove_from_client()
     self._removed_sim = self.sim
     self._client = self.sim.client
     if from_reset:
         self._finalize_death()
         self.sim.schedule_destroy_asap(source=self.sim, cause='Sim reset during death.')
     else:
         self.add_exit_function(self.run_post_death_behavior)
 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_phone_choices(control:int=0, alt:int=0, shift:int=0, reference_id:int=0, _connection=None):
    zone = services.current_zone()
    client = zone.client_manager.get(_connection)
    sim = _active_sim(client)
    if sim is None:
        return 0
    shift_held = bool(shift)
    context = client.create_interaction_context(sim, shift_held=shift_held)
    can_queue_interactions = sim.queue is None or sim.queue.can_queue_visible_interaction()
    if can_queue_interactions:
        pie_menu_action = PieMenuActions.SHOW_PIE_MENU
        choice_menu = ChoiceMenu(sim.potential_phone_interactions(context), context)
        client.set_choices(choice_menu)
    else:
        pie_menu_action = PieMenuActions.INTERACTION_QUEUE_FULL_TOOLTIP
        choice_menu = None
    msg = create_pie_menu_message(sim, context, choice_menu, reference_id, pie_menu_action)
    distributor = Distributor.instance()
    distributor.add_event(Consts_pb2.MSG_PHONE_MENU_CREATE, msg, True)
    with telemetry_helper.begin_hook(writer, TELEMETRY_HOOK_CREATE_PIE_MENU, sim=sim) as hook:
        hook.write_int('piid', reference_id)
        hook.write_string('kind', 'phone')
    return len(msg.items)