class ItemCost(ItemCostBase, AutoFactoryInit, HasTunableSingletonFactory): UNAVAILABLE_TOOLTIP_HEADER = TunableLocalizedStringFactory( description= '\n A string to be used as a header for a bulleted list of items that the\n Sim is missing in order to run this interaction.\n ' ) AVAILABLE_TOOLTIP_HEADER = TunableLocalizedStringFactory( description= '\n A string to be used as a header for a bulleted list of items that the\n Sim will consume in order to run this interaction.\n ' ) FACTORY_TUNABLES = { 'ingredients': TunableList( description= '\n List of tuples of Objects and Quantity, which will indicate\n the cost of items for this interaction to run\n ', tunable=TunableTuple( description= '\n Pair of Object and Quantity needed for this interaction\n ', ingredient=TunableReference( description= '\n Object reference of the type of game object needed.\n ', manager=services.definition_manager()), quantity=TunableRange( description= '\n Quantity of objects needed\n ', tunable_type=int, default=1, minimum=1), missing_ingredient_additional_text=OptionalTunable( description= '\n If set, this text is inserted on a new line following a missing ingredient.\n ', tunable=TunableLocalizedString( default=None, description='The string key of the text description' )))) }
class FishingBait(HasTunableSingletonFactory, AutoFactoryInit): FACTORY_TUNABLES = { 'bait_name': TunableLocalizedStringFactory( description='\n Name of fishing bait.\n '), 'bait_description': TunableLocalizedStringFactory( description= '\n Description of fishing bait.\n '), 'bait_icon_definition': TunableReference( description= '\n Object definition that will be used to render icon of fishing bait.\n ', manager=services.definition_manager()), 'bait_buff': TunableReference( description='\n Buff of fishing bait.\n ', manager=services.buff_manager()), 'bait_priority': TunableRange( description= '\n The priority of the bait. When an object can be categorized into\n multiple fishing bait categories, the highest priority category \n will be chosen.\n ', tunable_type=int, default=1, minimum=1) }
def __init__(self, **kwargs): super().__init__( cancelable=Tunable( description= '\n If this tutorial tip can be canceled.\n ', tunable_type=bool, default=True), text=TunableLocalizedStringFactory( description= "\n The text for this tip.\n Token {0} is the active sim. i.e. {0.SimFirstName}\n Token {1.String} is a 'wildcard' string to be used for things\n like aspiration names or buff names during the tutorial.\n Not used when display type is INDICATOR_ARROW.\n ", allow_none=True), action_text=TunableLocalizedStringFactory( description= "\n The action the user must make for this tip to satisfy.\n Token {0} is the active sim. i.e. {0.SimFirstName}\n Token {1.String} is a 'wildcard' string to be used for things\n like aspiration names or buff names during the tutorial.\n ", allow_none=True), timeout=TunableRange( description= '\n How long, in seconds, until this tutorial tip times out.\n ', tunable_type=int, default=1, minimum=1), ui_element=TunableEnumEntry( description= '\n The UI element associated with this tutorial tip.\n ', tunable_type=TutorialTipUiElement, default=TutorialTipUiElement.UI_INVALID), is_modal=Tunable( description= '\n Enable if this tip should be modal.\n Disable, if not.\n ', tunable_type=bool, default=False), icon=TunableResourceKey( description= '\n The icon to be displayed in a modal tutorial tip.\n If Is Modal is disabled, this field can be ignored.\n ', resource_types=sims4.resources.CompoundTypes.IMAGE, default=None, allow_none=True), icon_console=TunableResourceKey( description= '\n The icon to be displayed in a modal tutorial tip on console.\n If unset, will fall back to Icon.\n If Is Modal is disabled, this field can be ignored.\n ', resource_types=sims4.resources.CompoundTypes.IMAGE, default=None, allow_none=True, display_name='Icon (Console)', export_modes=ExportModes.ClientBinary), title=TunableLocalizedString( description= '\n The title of this tutorial tip.\n Not used when display type is INDICATOR_ARROW.\n ', allow_none=True), pagination_label=TunableLocalizedString( description= '\n The label of what page this tutorial tip is in within the\n tutorial tip group.\n Not used when display type is INDICATOR_ARROW.\n ', allow_none=True), display_type_option=TunableEnumEntry( description= '\n The display type of this tutorial tip.\n ', tunable_type=TutorialTipDisplayOption, default=TutorialTipDisplayOption.STANDARD), **kwargs)
class SpellbookTuning: FRONT_PAGE_DATA = TunableTuple(description='\n UI-specific data used to display front page.\n ', title=TunableLocalizedStringFactory(description='\n The title to use on the front page of the spellbook.\n '), icon=OptionalTunable(description='\n Image displayed on front page of spellbook.\n If unset, image is not shown.\n ', tunable=TunableIconAllPacks()), page_description=OptionalTunable(description='\n Description used for this page in the spellbook.\n If unset, description is not shown.\n ', tunable=TunableLocalizedString())) CATEGORY_LIST_DATA = TunableTuple(description='\n UI-specific data used to display second page of the spellbook.\n ', title=TunableLocalizedStringFactory(description='\n The title to use on the category list of the spellbook.\n '), icon=OptionalTunable(description='\n Icon used on the category list page of the spellbook.\n ', tunable=TunableIconAllPacks()), page_description=OptionalTunable(description='\n Description used for this page in the spellbook.\n If unset, description is not shown.\n ', tunable=TunableLocalizedString())) CATEGORY_DATAS = TunableList(description='\n A list of a spellbook category data.\n ', tunable=SpellbookCategoryData.TunableFactory(), tuning_group=GroupNames.UI) POTION_DISPLAY_DATA = TunableMapping(description="\n A mapping of a potion's recipe to it's spellbook display data. \n ", key_type=TunableReference(description="\n The potion's recipe.\n ", manager=services.get_instance_manager(Types.RECIPE), class_restrictions=('Recipe',), pack_safe=True), value_type=SpellbookRecipeData.TunableFactory(), tuning_group=GroupNames.UI) INGREDIENTS_LABEL = TunableLocalizedString(description='\n Text used to display ingredients label for a spell or potion.\n \n e.g. "Ingredients:"\n ', tuning_group=GroupNames.UI) PROGRESS_LABEL = TunableLocalizedString(description='\n Text used to display field name for progress into a specific\n category.\n \n e.g. "Learned:"\n ', tuning_group=GroupNames.UI) PROGRESS_TEXT_FORMAT = TunableLocalizedStringFactory(description='\n Text used to display the progress towards completing a specific\n category. Takes current items learned and and total available.\n\n e.g. "{0.Number}/{1.Number}"\n ', tuning_group=GroupNames.UI) CATEGORY_FRONT_PAGE_ENTRY_COUNT = TunableRange(description=',\n Number of entries allotted for the front page of a category section.\n ', tunable_type=int, minimum=0, tuning_group=GroupNames.UI, default=2) CATEGORY_ENTRY_COUNT = TunableRange(description=',\n Number of entries allotted for the subsequent pages of a category section.\n ', tunable_type=int, minimum=1, tuning_group=GroupNames.UI, default=4) INGREDIENT_FORMAT = TunableLocalizedStringFactory(description='\n The format used for ingredients in the spellbook.\n First parameter will be name of ingredient, second will be quantity required.\n e.g. {0.String}({1.Number}) = "Frog(1)"\n ', tuning_group=GroupNames.UI)
class InteractionPickerItem(HasTunableSingletonFactory, AutoFactoryInit): FACTORY_TUNABLES = { 'icon': OptionalTunable( description= '\n If enabled, specify the icon to be displayed in UI.\n ', tunable=TunableIconVariant()), 'name': OptionalTunable( description= '\n If enabled, display this name in the UI.\n \n Otherwise the display name of the first affordance\n in the continuation will be used as the name.\n ', tunable=TunableLocalizedStringFactory()), 'item_description': OptionalTunable( description= '\n When enabled, the tuned string will be shown as a description.\n ', tunable=TunableLocalizedStringFactory()), 'item_tooltip': OptionalTunable( description= '\n When enabled, the tuned string will be shown as a tooltip.\n ', tunable=TunableLocalizedStringFactory()), 'disable_tooltip': OptionalTunable( description= '\n When tuned, and the item is disabled, the tuned string \n will be shown as a tooltip.\n \n Otherwise it will try to grab a tooltip off a failed test.\n ', tunable=TunableLocalizedStringFactory()), 'continuation': TunableContinuation( description= '\n The continuation to push when this item is selected.\n ', minlength=1), 'enable_tests': OptionalTunable( description= '\n Tests which would dictate if this option is enabled\n in the pie menu. ORs of ANDs.\n \n If disabled, it will default to the tests for the\n first affordance in the continuation chain.\n ', tunable=TunableTestSet()), 'localization_tokens': OptionalTunable( description= "\n Additional localization tokens for this item\n to use in the name/description.\n \n This is in addition to the display name tokens\n tuned in the continuation's first affordance.\n ", tunable=LocalizationTokens.TunableFactory()), 'visibility_tests': OptionalTunable( description= '\n Tests which would dictate if this option is visible\n in the pie menu. ORs of ANDs.\n \n If disabled, this item will always be visible.\n ', tunable=TunableTestSet()) }
class PieMenuActions(enum.Int, export=False): __qualname__ = 'PieMenuActions' SHOW_PIE_MENU = 0 SHOW_DEBUG_PIE_MENU = 1 INTERACTION_QUEUE_FULL_TOOLTIP = 2 INTERACTION_QUEUE_FULL_STR = TunableLocalizedStringFactory(description="\n Tooltip string shown to the user instead of a pie menu when the Sim's queue\n is full of interactions.\n ") POSTURE_INCOMPATIBLE_ICON = TunableResourceKey(description='\n Icon to be displayed when pie menu option is not compatible with\n current posture of the sim.\n ', default='PNG:missing_image', resource_types=sims4.resources.CompoundTypes.IMAGE)
class PhoneTuning: DISABLE_PHONE_TESTS = TunableList( description= '\n List of tests and tooltip that when passed will disable opening the\n phone.\n ', tunable=TunableTuple( description= '\n Test that should pass for the phone to be disabled and its tooltip\n to display to the player when he clicks on the phone.\n ', test=TunableTestVariant(), tooltip=TunableLocalizedStringFactory())) class TunablePhoneColorTuple(TunableTuple): def __init__(self, *args, **kwargs): super().__init__( *args, bg_image=TunableIcon( description= '\n Image resource to display as UI phone panel background.\n ' ), icon=TunableIcon( description= '\n Icon to display for phone color selector swatch.\n ' ), phone_trait=TunableReference( description= '\n Trait associated with cell phone color.\n ', allow_none=True, manager=services.get_instance_manager( sims4.resources.Types.TRAIT)), **kwargs) PHONE_COLOR_VARIATION_TUNING = TunableList( description= '\n A list of all of the different colors you can set the cell phone cover to be.\n ', tunable=TunablePhoneColorTuple(), export_modes=(ExportModes.ClientBinary, ))
class CasStoriesAnswer(HasTunableReference, metaclass=HashedTunedInstanceMetaclass, manager=services.get_instance_manager( sims4.resources.Types.CAS_STORIES_ANSWER)): INSTANCE_TUNABLES = { 'text': TunableLocalizedStringFactory( description='\n The text of this answer.\n ', export_modes=ExportModes.ClientBinary, tuning_group=GroupNames.UI), 'weightings': TunableList( description= '\n A list of objects to apply weightings to if this answer is \n selected. Weight is the weight that shoudld be added to the chance \n to receive this object. In the latter case a trait will be \n selected from the trait chooser based on its cumulative weighting \n throughout the CAS Stories survey.\n ', tunable=TunableTuple(weighted_object=TunableVariant( trait=Trait.TunableReference(), trait_chooser=CasStoriesTraitChooser.TunableReference(), aspiration_track=TunableReference( manager=services.get_instance_manager( sims4.resources.Types.ASPIRATION_TRACK)), default='trait'), weight=Tunable(tunable_type=float, default=0.0), export_class_name='CASAnswerWeightings'), export_modes=ExportModes.ClientBinary) }
class ShutOffUtilityModifier(HasTunableFactory, AutoFactoryInit): FACTORY_TUNABLES = { 'utility': TunableEnumEntry( description= '\n The household utility we want to modify.\n ', tunable_type=Utilities, default=Utilities.POWER), 'shutoff_tooltip': TunableLocalizedStringFactory( description= '\n A tooltip to show when an interaction cannot be run due to this\n utility being shutoff.\n ' ), 'shutoff_reason': TunableEnumEntry( description= '\n The priority of our shutoff reason. This determines how important\n the shutoff tooltip is relative to other reasons the utility is\n being shutoff.\n ', tunable_type=UtilityShutoffReasonPriority, default=UtilityShutoffReasonPriority.NO_REASON) } def start(self, household_id): utilities_manager = services.utilities_manager(household_id) utilities_manager.shut_off_utility(self.utility, self.shutoff_reason, self.shutoff_tooltip) def stop(self, household_id): utilities_manager = services.utilities_manager(household_id) utilities_manager.restore_utility(self.utility, self.shutoff_reason)
class _TextInputLengthFixed(HasTunableSingletonFactory, AutoFactoryInit): FACTORY_TUNABLES = { 'min_length': OptionalTunable( description= "\n If enabled, specify the minimum length of input text the player has\n to enter before he/she can hit the 'OK' button.\n ", tunable=TunableTuple( length=TunableRange( description= '\n Minimum amount of characters the user must enter in to the\n text box before he/she can click on the OK button.\n ', tunable_type=int, minimum=1, default=1), tooltip=OptionalTunable( description= '\n If enabled, allows specification of a tooltip to display if\n the user has entered text length less than min_length.\n ', tunable=TunableLocalizedStringFactory()))), 'max_length': Tunable( description= '\n Max amount of characters the user can enter into the text box.\n ', tunable_type=int, default=20) } def build_msg(self, dialog, msg, *additional_tokens): msg.max_length = self.max_length if self.min_length is not None: msg.min_length = self.min_length.length if self.min_length.tooltip is not None: msg.input_too_short_tooltip = dialog._build_localized_string_msg( self.min_length.tooltip, *additional_tokens)
class PackSpecificTuning: VENUE_PACK_TUNING = TunableMapping( description= "\n Venue tuning that is needed by UI when that venue's pack is not installed.\n ", key_name='venue_id', key_type=TunableReference( description= '\n Reference to the venue that this data represents\n ', manager=services.get_instance_manager(sims4.resources.Types.VENUE), pack_safe=True), value_name='data', value_type=TunableTuple( description= "\n Venue data that is shown in the UI when this venue's pack is not installed.\n ", gallery_download_venue=OptionalTunable( description= '\n If tuned, the tuned venue tuning will be substituted if this\n venue is downloaded from the gallery by a player who is not\n entitled to it. The default behavior is to substitute the\n generic venue. This tuned venue will also determine download\n compatibility (for instance, only residential venues can be \n downloaded to owned residential venues).\n ', tunable=TunableReference(manager=services.get_instance_manager( sims4.resources.Types.VENUE))), venue_name=TunableLocalizedStringFactory( description= '\n Name that will be displayed for the venue when the pack containing \n that venue is not installed\n ' ), venue_flags=TunableEnumFlags( description= '\n Venue flags used to mark a venue with specific properties.\n ', enum_type=VenueFlags, allow_no_flags=True, default=VenueFlags.NONE), export_class_name='VenueDataTuple'), tuple_name='VenuePackTuning', export_modes=ExportModes.All, verify_tunable_callback=verify_venue_tuning)
class UiDialogOk(UiDialog): __qualname__ = 'UiDialogOk' FACTORY_TUNABLES = { 'text_ok': TunableLocalizedStringFactory( description='\n The OK button text.\n ', default=3648501874), 'is_special_dialog': Tunable( description= '\n If checked, UI will treat this as a special ok or ok/cancel dialog \n and represent the ok or ok/cancel options in a special way. \n They will use the text as a tooltip for ok or ok/cancel options \n and use particular icons for the buttons.\n ', tunable_type=bool, default=False) } def build_msg(self, **kwargs): msg = super().build_msg(**kwargs) if self.is_special_dialog: msg.dialog_type = Dialog_pb2.UiDialogMessage.OK_CANCEL_ICONS return msg @property def accepted(self) -> bool: return self.response == ButtonType.DIALOG_RESPONSE_OK @property def responses(self): return (UiDialogResponse( dialog_response_id=ButtonType.DIALOG_RESPONSE_OK, text=self.text_ok, ui_request=UiDialogResponse.UiDialogUiRequest.NO_REQUEST), )
class TravelMixin: __qualname__ = 'TravelMixin' PENDING_TRAVEL_TOOLTIP = TunableLocalizedStringFactory(description='Greyed out tooltip shown when trying to travel with a pending travel reservation.') def __init__(self, *args, to_zone_id=0, **kwargs): super().__init__(to_zone_id=to_zone_id, *args, **kwargs) self.to_zone_id = to_zone_id @classmethod def travel_test(cls, context): zone = services.current_zone() if zone.travel_service.has_pending_travel(context.sim.account): return TestResult(False, 'Cannot Travel... with a pending travel already queued!', tooltip=cls.PENDING_TRAVEL_TOOLTIP) return TestResult.TRUE def show_travel_dialog(self): if self.sim.client is None: return travel_info = InteractionOps_pb2.TravelMenuCreate() travel_info.sim_id = self.sim.sim_id travel_info.selected_lot_id = self.to_zone_id travel_info.selected_world_id = self._kwargs.get('world_id', 0) travel_info.selected_lot_name = self._kwargs.get('lot_name', '') travel_info.friend_account = self._kwargs.get('friend_account', '') system_distributor = distributor.system.Distributor.instance() system_distributor.add_op_with_no_owner(GenericProtocolBufferOp(DistributorOps_pb2.Operation.TRAVEL_MENU_SHOW, travel_info))
class RenameImmediateInteraction(ImmediateSuperInteraction): __qualname__ = 'RenameImmediateInteraction' TEXT_INPUT_NEW_NAME = 'new_name' TEXT_INPUT_NEW_DESCRIPTION = 'new_description' INSTANCE_TUNABLES = {'display_name_rename': OptionalTunable(TunableLocalizedStringFactory(description="If set, this localized string will be used as the interaction's display name if the object has been previously renamed.")), 'rename_dialog': TunableVariant(description='\n The rename dialog to show when running this interaction.\n ', ok_dialog=UiDialogTextInputOk.TunableFactory(text_inputs=(TEXT_INPUT_NEW_NAME, TEXT_INPUT_NEW_DESCRIPTION)), ok_cancel_dialog=UiDialogTextInputOkCancel.TunableFactory(text_inputs=(TEXT_INPUT_NEW_NAME, TEXT_INPUT_NEW_DESCRIPTION)))} @flexmethod def _get_name(cls, inst, target=DEFAULT, context=DEFAULT, **kwargs): inst_or_cls = inst if inst is not None else cls target = inst.target if inst is not None else target if inst_or_cls.display_name_rename is not None and target.has_custom_name(): display_name = inst_or_cls.display_name_rename else: display_name = inst_or_cls.display_name return inst_or_cls.create_localized_string(display_name, target=target, context=context, **kwargs) def _run_interaction_gen(self, timeline): target_name_component = self.target.name_component def on_response(dialog): if not dialog.accepted: return name = dialog.text_input_responses.get(self.TEXT_INPUT_NEW_NAME) description = dialog.text_input_responses.get(self.TEXT_INPUT_NEW_DESCRIPTION) target = self.target if target is not None: if name is not None: target.set_custom_name(name) if description is not None: target.set_custom_description(description) self._update_ui_metadata(target) sequence = self._build_outcome_sequence() services.time_service().sim_timeline.schedule(element_utils.build_element(sequence)) text_input_overrides = {} (template_name, template_description) = target_name_component.get_template_name_and_description() if target_name_component.allow_name: text_input_overrides[self.TEXT_INPUT_NEW_NAME] = None if self.target.has_custom_name(): text_input_overrides[self.TEXT_INPUT_NEW_NAME] = lambda *_, **__: LocalizationHelperTuning.get_object_name(self.target) elif template_name is not None: text_input_overrides[self.TEXT_INPUT_NEW_NAME] = template_name if target_name_component.allow_description: text_input_overrides[self.TEXT_INPUT_NEW_DESCRIPTION] = None if self.target.has_custom_description(): text_input_overrides[self.TEXT_INPUT_NEW_DESCRIPTION] = lambda *_, **__: LocalizationHelperTuning.get_object_description(self.target) elif template_description is not None: text_input_overrides[self.TEXT_INPUT_NEW_DESCRIPTION] = template_description dialog = self.rename_dialog(self.sim, self.get_resolver()) dialog.show_dialog(on_response=on_response, text_input_overrides=text_input_overrides) return True def build_outcome(self): pass def _update_ui_metadata(self, updated_object): updated_object.update_ui_metadata() current_inventory = updated_object.get_inventory() if current_inventory is not None: current_inventory.push_inventory_item_update_msg(updated_object)
class UiDialogInfoInColumns(UiDialogOk): FACTORY_TUNABLES = { 'column_headers': TunableList( description= '\n A list of column header strings.\n ', tunable=TunableLocalizedStringFactory()) } def build_msg(self, row_data=[], additional_tokens=(), **kwargs): msg = super().build_msg(additional_tokens=additional_tokens, **kwargs) msg.dialog_type = Dialog_pb2.UiDialogMessage.INFO_IN_COLUMNS sim_info = self.owner.sim_info msg.override_sim_icon_id = self.owner.id if self.owner is not None else 0 if sim_info is None: logger.error('Sim Info was None for {}', self._target_sim_id) return msg info_columns_msg = Dialog_pb2.UiDialogInfoInColumns() for column_header in self.column_headers: info_columns_msg.column_headers.append(column_header(sim_info)) for row in row_data: row_data_msg = Dialog_pb2.UiDialogRowData() for (icon, icon_name, icon_description) in row: icon_data = IconInfoData(icon_resource=icon) icon_info_msg = create_icon_info_msg(icon_data, name=icon_name, desc=icon_description) row_data_msg.column_info.append(icon_info_msg) info_columns_msg.rows.append(row_data_msg) msg.info_in_columns_data = info_columns_msg return msg
class TestableDisplayName(HasTunableSingletonFactory, AutoFactoryInit): __qualname__ = 'TestableDisplayName' @staticmethod def _verify_tunable_callback(instance_class, tunable_name, source, value): for (index, override_data) in enumerate(value.overrides): while not override_data.new_display_name: logger.error( 'name override not set for display name override in {} at index:{}', instance_class, index) FACTORY_TUNABLES = { 'overrides': TunableList( description= '\n Potential name overrides for this interaction. The first test in\n this list which passes will be the new display name show to the\n player. If none pass the tuned display_name will be used.\n ', tunable=TunableTuple( description= '\n A tuple of a test and the name that would be chosen if the test\n passes.\n ', test=event_testing.tests.TunableTestSet( description= '\n The test to run to see if the display_name should be\n overridden.\n ' ), new_display_name=TunableLocalizedStringFactory( description= '\n The localized name of this interaction. it takes two tokens,\n the actor (0) and target object (1) of the interaction.\n ' ), new_pie_menu_icon=TunableResourceKey( description= '\n If this display name overrides the default display name,\n this will be the icon that is shown. If this is not tuned\n then the default pie menu icon for this interaction will be\n used.\n ', default=None, resource_types=sims4.resources.CompoundTypes.IMAGE), new_display_tooltip=OptionalTunable( description= '\n Tooltip to show on this pie menu option.\n ', tunable=sims4.localization.TunableLocalizedStringFactory( )), new_pie_menu_category=TunableReference( description= '\n Pie menu category to put interaction under.\n ', manager=services.get_instance_manager( sims4.resources.Types.PIE_MENU_CATEGORY)))), 'verify_tunable_callback': _verify_tunable_callback } def get_display_names_gen(self): for override in self.overrides: yield override.new_display_name def get_display_name_and_result(self, interaction, target=DEFAULT, context=DEFAULT): resolver = interaction.get_resolver(target=target, context=context) for override in self.overrides: result = override.test.run_tests(resolver) while result: return (override, result) return (None, TestResult.NONE)
class TunableDisplayNameWrapper(HasTunableSingletonFactory, AutoFactoryInit): FACTORY_TUNABLES = { 'wrappers': TunableList( description= '\n Each wrapper is a localized string matched with a test set. The \n wrapper that tests in first is applied to the display name.\n \n NOTE: The wrapper is override independent, and if enabled will be \n applied to all display name variants. Anything that depends on override\n context should not be tuned here, but instead be tuned manually under\n Display Name Overrides.\n \n NOTE: The format of the wrapper will take in the original string\n and should be written in this form: "[0.String] Wrapper" .\n ', tunable=TunableTuple( description= '\n A tuple of test sets and the wrapper.\n ', test=event_testing.tests.TunableTestSet( description= '\n The tests that control the condition of when the wrapper is\n displayed.\n ' ), wrapper=TunableLocalizedStringFactory( description= '\n The localized wrapper.\n ' ))) } def get_first_passing_wrapper(self, interaction, target=DEFAULT, context=DEFAULT, **interaction_parameters): resolver = interaction.get_resolver(target=target, context=context, **interaction_parameters) for wrapper in self.wrappers: result = wrapper.test.run_tests(resolver) if result: return wrapper
class UiDialogResponse(HasTunableSingletonFactory, AutoFactoryInit): __qualname__ = 'UiDialogResponse' class UiDialogUiRequest(enum.Int): __qualname__ = 'UiDialogResponse.UiDialogUiRequest' NO_REQUEST = 0 SHOW_LESSONS = 1 SHOW_ACHIEVEMENTS = 2 SHOW_GALLERY = 3 SHOW_FAMILY_INVENTORY = 4 SHOW_SKILL_PANEL = 5 SHOW_SUMMARY_PANEL = 6 SHOW_ASPIRATION_PANEL = 7 SHOW_ASPIRATION_UI = 8 SHOW_EVENT_UI = 9 SHOW_CAREER_PANEL = 10 SHOW_RELATIONSHIP_PANEL = 11 SHOW_SIM_INVENTORY = 12 SHOW_REWARD_STORE = 13 SHOW_MOTIVE_PANEL = 14 SHOW_STATS = 15 SHOW_COLLECTIBLES = 16 SHOW_CAREER_UI = 17 TRANSITION_TO_NEIGHBORHOOD_SAVE = 18 TRANSITION_TO_MAIN_MENU_NO_SAVE = 19 SHOW_SHARE_PLAYER_PROFILE = 20 SHOW_ASPIRATION_SELECTOR = 21 FACTORY_TUNABLES = { 'sort_order': Tunable( description= '\n The sorting order of the response button. If the items of the\n same order will be placed in the order that they are added.\n ', tunable_type=int, default=0), 'dialog_response_id': TunableEnumEntry(description='\n ', tunable_type=ButtonType, default=ButtonType.DIALOG_RESPONSE_NO_RESPONSE), 'text': TunableLocalizedStringFactory( description="\n The prompt's text.\n "), 'ui_request': TunableEnumEntry( description= "\n This prompt's associated UI action.\n ", tunable_type=UiDialogUiRequest, default=UiDialogUiRequest.NO_REQUEST) } def __init__(self, sort_order=0, dialog_response_id=ButtonType.DIALOG_RESPONSE_NO_RESPONSE, text=None, ui_request=UiDialogUiRequest.NO_REQUEST): super().__init__(sort_order=sort_order, dialog_response_id=dialog_response_id, text=text, ui_request=ui_request)
class UiDialogOkCancel(UiDialogOk): FACTORY_TUNABLES = { 'text_cancel': TunableLocalizedStringFactory(description = '\n The Cancel button text.\n ', default = 3497542682) } @property def responses (self): return (UiDialogResponse(dialog_response_id = ButtonType.DIALOG_RESPONSE_OK, text = self.text_ok, ui_request = UiDialogResponse.UiDialogUiRequest.NO_REQUEST), UiDialogResponse(dialog_response_id = ButtonType.DIALOG_RESPONSE_CANCEL, text = self.text_cancel, ui_request = UiDialogResponse.UiDialogUiRequest.NO_REQUEST))
class RandomDisplayName(HasTunableSingletonFactory, AutoFactoryInit): __qualname__ = 'RandomDisplayName' FACTORY_TUNABLES = { 'overrides': TunableList( description= '\n A list of random strings and icons to select randomly.\n ', tunable=TunableTuple( new_display_name=TunableLocalizedStringFactory(), new_pie_menu_icon=TunableResourceKey( default=None, resource_types=sims4.resources.CompoundTypes.IMAGE), new_display_tooltip=OptionalTunable( description= '\n Tooltip to show on this pie menu option.\n ', tunable=sims4.localization.TunableLocalizedStringFactory( )), locked_args={'new_pie_menu_category': None})), 'timeout': TunableSimMinute( description= '\n The time it will take for a new string to be generated given the\n same set of data.\n ', minimum=0, default=10) } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._key_map = {} def get_display_names_gen(self): for override in self.overrides: yield override.new_display_name def get_display_name_and_result(self, interaction, target=DEFAULT, context=DEFAULT): context = interaction.context if context is DEFAULT else context target = interaction.target if target is DEFAULT else target key = (context.sim.id, 0 if target is None else target.id, interaction.affordance) random_names = getattr(context, 'random_names', dict()) result = random_names.get(key) if result is not None: return (result, TestResult.NONE) now = services.time_service().sim_now result_and_timestamp = self._key_map.get(key) if result_and_timestamp is not None: time_delta = now - result_and_timestamp[1] if self.timeout > time_delta.in_minutes(): self._key_map[key] = (result_and_timestamp[0], now) return (result_and_timestamp[0], TestResult.NONE) result = random.choice(self.overrides) random_names[key] = result setattr(context, 'random_names', random_names) self._key_map[key] = (result, now) return (result, TestResult.NONE)
class _MoodCategory(HasTunableSingletonFactory, AutoFactoryInit): FACTORY_TUNABLES = { 'icon_tuning': TunableTuple( description= "\n A set of icons to associate with this mood category. Different\n icons are for different states of the mood category's button in\n the UI.\n ", up_icon=TunableIconAllPacks(), down_icon=TunableIconAllPacks(), over_icon=TunableIconAllPacks()), 'tooltip': TunableLocalizedStringFactory( description= '\n The tooltip for this category in the photography UI.\n ' ), 'mood_param_values': TunableList( description= '\n A list of mood param values (strings). One of these will be\n selected at random if a player selects this category in the UI.\n ', tunable=Tunable(tunable_type=str, default=None), minlength=1), 'target_tests_pass_one': TunableTestSet( description= '\n A set of tests which will be run on every photo target. The\n target will be the Target Participant and the photographer will\n be the Actor participant. These tests must pass for at least\n one target for this mood category to be included.\n ' ), 'target_tests_pass_all': TunableTestSet( description= '\n A set of tests which will be run on every photo target. The\n target will be the Target Participant and the photographer will\n be the Actor participant. These tests must pass for all targets\n for this mood category to be included.\n ' ), 'test_for_incest': Tunable( description= '\n If checked, this mood category will be disabled if any pair of\n targets fails the incest test.\n ', tunable_type=bool, default=False) } def run_tests(self, photographer, targets): if len(targets) > 1: if self.test_for_incest: target_combinations = itertools.combinations(targets, 2) for (sim_a, sim_b) in target_combinations: if not sim_a.sim_info.incest_prevention_test( sim_b.sim_info): return False passed_one = False for target in targets: resolver = DoubleSimResolver(photographer, target) if self.target_tests_pass_one.run_tests(resolver): passed_one = True if not self.target_tests_pass_all.run_tests(resolver): return False if not passed_one: return False return True
class AgingTuning: AGING_DATA = TunableMapping(description='\n On a per-species level, define all age-related data.\n ', key_type=TunableEnumEntry(description='\n The species this aging data applies to.\n ', tunable_type=Species, default=Species.HUMAN, invalid_enums=(Species.INVALID,), binary_type=EnumBinaryExportType.EnumUint32), value_type=AgingData.TunableFactory(), tuple_name='AgingDataMapping') AGING_SAVE_LOCK_TOOLTIP = TunableLocalizedStringFactory(description='\n The tooltip to show in situations where save-lock during Age Up is\n necessary, i.e. when babies or non-NPC Sims age up.\n \n This tooltip is provided one token: the Sim that is aging up.\n ') AGE_SPEED_SETTING_MULTIPLIER = TunableMapping(description='\n A mapping between age speeds and the multiplier that those speeds\n correspond to.\n ', key_type=TunableEnumEntry(description='\n The age speed that will be mapped to its multiplier.\n ', tunable_type=AgeSpeeds, default=AgeSpeeds.NORMAL), value_type=Tunable(description="\n The multiplier by which to adjust the lifespan based on user age\n speed settings. Setting this to 2 for 'Slow' speed will double the\n Sim's age play time in that setting.\n ", tunable_type=float, default=1)) AGE_PROGRESS_UPDATE_TIME = Tunable(description='\n The update rate, in Sim Days, of age progression in the UI.\n ', tunable_type=float, default=0.2) AGE_SUPPRESSION_ALARM_TIME = TunableSimMinute(description='\n Amount of time in sim seconds to suppress aging.\n ', default=5, minimum=1) @classmethod def get_aging_data(cls, species): return cls.AGING_DATA[species]
def get_object_picker_row(self): return ObjectPickerRow( count=0, option_id=self.get_option_id(), name=self.get_name(), row_description=self.get_description(), row_tooltip=None if self.skip_tooltip else TunableLocalizedStringFactory._Wrapper( self.get_description().hash), icon=self.get_icon(), tag=self.get_tag())
class CraftingObjectType(metaclass=TunedInstanceMetaclass, manager=services.get_instance_manager( sims4.resources.Types.RECIPE)): __qualname__ = 'CraftingObjectType' INSTANCE_TUNABLES = { 'unavailable_tooltip': TunableLocalizedStringFactory( description= 'Tooltip displayed when there are no objects of this type and one is required.' ) }
class _LiteralString(HasTunableSingletonFactory, AutoFactoryInit): FACTORY_TUNABLES = { 'text': TunableLocalizedStringFactory( description= '\n The text to be shown.\n \n * Token 0: Sim\n ' ) } def get_string(self, sim_info): return self.text(sim_info)
class TraitToDefinitionPickerInteraction(ObjectDefinitionPickerInteraction): INSTANCE_TUNABLES = { 'trait_to_definition_id': TunableMapping( description= '\n Backward mapping of trait to what umbrella the sim carries\n ', key_type=Trait.TunableReference( description= '\n Trait to look for\n '), value_type=TunableReference( description= '\n The object must have this definition.\n ', manager=services.definition_manager())), 'disabled_toolip': TunableLocalizedStringFactory( description= '\n Tooltip that displays if the sim currently has the trait in the mapping.\n ' ) } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._selected_definition_id = None def _create_dialog(self, owner, target_sim=None, target=None, **kwargs): traits_to_find = self.trait_to_definition_id.keys() for trait in traits_to_find: if not owner.has_trait(trait): continue self._selected_definition_id = self.trait_to_definition_id[trait] break return super()._create_dialog(owner, target_sim=target_sim, target=target, **kwargs) @flexmethod def create_row(cls, inst, row_obj, context=DEFAULT, target=DEFAULT): inst_or_cls = inst if inst is not None else cls is_disabled = inst_or_cls._selected_definition_id is not None and row_obj.id == inst_or_cls._selected_definition_id.id icon_info = IconInfoData(obj_def_id=row_obj.id, obj_geo_hash=row_obj.thumbnail_geo_state_hash, obj_material_hash=row_obj.material_variant) row = ObjectPickerRow( object_id=row_obj.id, def_id=row_obj.id, icon_info=icon_info, tag=row_obj, is_enable=not is_disabled, row_tooltip=inst_or_cls.disabled_toolip if is_disabled else None, name=LocalizationHelperTuning.get_object_name(row_obj)) inst_or_cls._test_continuation(row, context=context, target=target) return row
class FundsTuning: UNAFFORDABLE_TOOLTIPS = TunableMapping( description= '\n A mapping of tooltips for each of the funds sources when an interaction\n cannot be performed due to lack of such funds. Each tooltip takes the\n same tokens as the interaction.\n ', key_type=TunableEnumEntry( description='\n The funds source.\n ', tunable_type=FundsSource, default=FundsSource.HOUSEHOLD), value_type=TunableLocalizedStringFactory( description= '\n The tooltip to display when a Sim cannot run the specified\n interaction due to lack of funds.\n ' ))
class ShutOffUtility(AutoFactoryInit, HasTunableSingletonFactory): FACTORY_TUNABLES = { 'shutoff_tooltip': TunableLocalizedStringFactory( description= '\n A tooltip to show when an interaction cannot be run due to this\n utility being shutoff.\n ' ) } def __call__(self, utility_manager, utility, shutoff_reason): utility_manager.shut_off_utility(utility, shutoff_reason, self.shutoff_tooltip)
class SetFrontDoorImmediateInteraction(ImmediateSuperInteraction): __qualname__ = 'SetFrontDoorImmediateInteraction' INSTANCE_TUNABLES = {'already_front_door_tooltip': TunableLocalizedStringFactory(description='The greyed out tooltip if a player clicks on a door that is already their front door.')} @classmethod def _test(cls, target, context, **kwargs): if target.welcome_component: return TestResult(False, 'This door is already the front door.', tooltip=cls.already_front_door_tooltip) return TestResult.TRUE def _run_interaction_gen(self, timeline): self.target.set_as_front_door()
class ItemCost(AutoFactoryInit, HasTunableSingletonFactory): __qualname__ = 'ItemCost' UNAVAILABLE_TOOLTIP_HEADER = TunableLocalizedStringFactory(description='\n A string to be used as a header for a bulleted list of items that the\n Sim is missing in order to run this interaction.\n ') AVAILABLE_TOOLTIP_HEADER = TunableLocalizedStringFactory(description='\n A string to be used as a header for a bulleted list of items that the\n Sim will consume in order to run this interaction.\n ') FACTORY_TUNABLES = {'ingredients': TunableList(description='\n List of tuples of Objects and Quantity, which will indicate\n the cost of items for this interaction to run\n ', tunable=TunableTuple(description='\n Pair of Object and Quantity needed for this interaction\n ', ingredient=TunableReference(description='\n Object reference of the type of game object needed.\n ', manager=services.definition_manager()), quantity=TunableRange(description='\n Quantity of objects needed\n ', tunable_type=int, default=1, minimum=1)))} def consume_interaction_cost(self, interaction): def do_consume(*args, **kwargs): for item in self.ingredients: for _ in range(item.quantity): while not interaction.sim.inventory_component.try_destroy_object_by_definition(item.ingredient, source=interaction, cause='Consuming the cost of the interaction'): return False return True return do_consume def get_test_result(self, sim, cls): unavailable_items = Counter() for item in self.ingredients: item_count = sim.inventory_component.get_item_quantity_by_definition(item.ingredient) while item_count < item.quantity: unavailable_items[item.ingredient] += item.quantity - item_count if unavailable_items: tooltip = LocalizationHelperTuning.get_bulleted_list(self.UNAVAILABLE_TOOLTIP_HEADER(sim), *tuple(LocalizationHelperTuning.get_object_count(count, item) for (item, count) in unavailable_items.items())) return event_testing.results.TestResult(False, "Sim doesn't have the required items in inventory.", tooltip=lambda *_, **__: tooltip) return TestResult.TRUE def get_interaction_tooltip(self, tooltip=None, sim=None): if self.ingredients: item_tooltip = LocalizationHelperTuning.get_bulleted_list(self.AVAILABLE_TOOLTIP_HEADER(sim), *tuple(LocalizationHelperTuning.get_object_count(ingredient.quantity, ingredient.ingredient) for ingredient in self.ingredients)) if tooltip is None: return item_tooltip return LocalizationHelperTuning.get_new_line_separated_strings(tooltip, item_tooltip) return tooltip def get_interaction_name(self, cls, display_name): for item in self.ingredients: display_name = cls.ITEM_COST_NAME_FACTORY(display_name, item.quantity, item.ingredient) return display_name