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)
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)
def execute_interaction(interaction) -> ExecuteResult: if interaction: if interaction.affordance.cheat: with telemetry_helper.begin_hook(sims4.commands.cheats_writer, sims4.commands.TELEMETRY_HOOK_INTERACTION) as hook: hook.write_string(sims4.commands.TELEMETRY_FIELD_NAME, interaction.__str__()) hook.write_string(sims4.commands.TELEMETRY_FIELD_TARGET, str(interaction.target)) if interaction.affordance.immediate: interaction._trigger_interaction_start_event() immediate_timeline = services.time_service().sim_timeline.get_sub_timeline() result_element = elements.ResultElement(elements.GeneratorElement(interaction._run_gen)) immediate_timeline.schedule(result_element) immediate_timeline.simulate(immediate_timeline.now) if immediate_timeline.heap: logger.error('On immediate execute_interaction, immediate timeline is not empty') immediate_timeline.heap.clear() run_result = result_element.result interaction._trigger_interaction_complete_test_event() if run_result: exit_behavior = interaction._exit(None, False) try: next(exit_behavior) logger.error('Running immediate exit_behavior yielded despite allow_yield=False') except StopIteration: pass execute_result = ExecuteResult(run_result, interaction, None) log_interaction('Immediate', interaction, '{}'.format(execute_result)) return execute_result context = interaction.context return ExecuteResult(context.sim.queue.append(interaction), interaction, None) return ExecuteResult(False, None, 'Trying to execute a None interaction.')
def 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()
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
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
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])
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)
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()
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))
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)
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)
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)
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)
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
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()))
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)
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)
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
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
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
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)
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 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)
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)
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
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)
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)
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()
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))
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 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')
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
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
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()
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)
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()
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 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)
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
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 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 _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)
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 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)