Example #1
0
 def _ui_metadata_gen(self):
     if GardeningTuning.is_spliced(self.owner):
         fruit_names = self.get_root_stock_names()
         description = LocalizationHelperTuning.get_comma_separated_list(
             *fruit_names)
         plant_name = GardeningTuning.SPLICED_PLANT_NAME()
     else:
         unidentified_overrides = self._unidentified_overrides
         if unidentified_overrides is not None and GardeningTuning.is_unidentified(
                 self.owner):
             description = unidentified_overrides.unidentified_description
             plant_name = unidentified_overrides.unidentified_name
         else:
             if self.is_shoot and self.root_stock is not None:
                 description = LocalizationHelperTuning.get_name_value_pair(
                     GardeningTuning.SHOOT_DESCRIPTION_STRING,
                     LocalizationHelperTuning.get_object_name(
                         self.root_stock.main_spawner.definition))
             else:
                 description = LocalizationHelperTuning.get_object_description(
                     self.owner.definition)
             plant_name = LocalizationHelperTuning.get_object_name(
                 self.owner.definition)
     yield ('recipe_name', plant_name)
     yield ('recipe_description', description)
     subtext = self.owner.get_state_strings()
     if subtext is not None:
         yield ('subtext', subtext)
 def _ui_metadata_gen(self):
     additional_information = self._get_additional_information()
     if additional_information and self.show_gardening_details():
         additional_information.sort()
         object_info_names = []
         object_info_descriptions = []
         bullet_points = []
         for (_, name, value) in additional_information:
             object_info_names.append(name)
             object_info_descriptions.append(value)
             bullet_point = LocalizationHelperTuning.get_name_value_pair(name, value)
             bullet_points.append(bullet_point)
         description = LocalizationHelperTuning.get_bulleted_list(None, *bullet_points)
         plant_name = LocalizationHelperTuning.get_object_name(self.owner.definition)
     else:
         object_info_names = None
         object_info_descriptions = None
         if GardeningTuning.is_spliced(self.owner):
             description = self._spliced_description
             plant_name = GardeningTuning.SPLICED_PLANT_NAME()
         else:
             if GardeningTuning.is_shoot(self.owner) and self.root_stock is not None:
                 description = LocalizationHelperTuning.get_object_name(self.root_stock.main_spawner)
             else:
                 description = LocalizationHelperTuning.get_object_description(self.owner.definition)
             plant_name = LocalizationHelperTuning.get_object_name(self.owner.definition)
     subtext = self.owner.get_state_strings()
     yield ('object_info_names', object_info_names)
     yield ('object_info_descriptions', object_info_descriptions)
     yield ('recipe_name', plant_name)
     yield ('recipe_description', description)
     if subtext is not None:
         yield ('subtext', subtext)
Example #3
0
 def return_lost_objects(self):
     returned_objects = defaultdict(list)
     current_zone = services.current_zone()
     current_zone_id = services.current_zone_id()
     current_open_street_id = current_zone.open_street_id
     active_household = services.active_household()
     for locator in list(self._object_locators):
         if locator.zone_id != current_zone_id:
             if locator.open_street_id != current_open_street_id:
                 elapsed_time = services.time_service(
                 ).sim_now - locator.time_stamp
                 if elapsed_time.in_minutes() < locator.time_before_lost:
                     continue
                 if locator.object_data is None:
                     self.remove_object(locator.object_id)
                 else:
                     (obj_returned,
                      owner) = self._return_lost_object(locator)
                     if obj_returned is not None:
                         if owner is not None:
                             if isinstance(owner, int):
                                 if owner == active_household.id:
                                     returned_objects[owner].append(
                                         obj_returned)
                                     if owner.household is active_household:
                                         returned_objects[owner].append(
                                             obj_returned)
                             elif owner.household is active_household:
                                 returned_objects[owner].append(
                                     obj_returned)
     if not returned_objects:
         return
     returned_objects_string = None
     household_manager = services.household_manager()
     for (owner, objects) in returned_objects.items():
         if isinstance(owner, int):
             household = household_manager.get(owner)
             header = ObjectLostAndFoundService.FAMILY_NAME_HEADER(
                 household.name)
             next_string = LocalizationHelperTuning.get_bulleted_list(
                 header,
                 *(LocalizationHelperTuning.get_object_name(obj)
                   for obj in objects))
         else:
             next_string = LocalizationHelperTuning.get_bulleted_list(
                 LocalizationHelperTuning.get_sim_name(owner),
                 *(LocalizationHelperTuning.get_object_name(obj)
                   for obj in objects))
         if returned_objects_string is None:
             returned_objects_string = next_string
         else:
             returned_objects_string = LocalizationHelperTuning.NEW_LINE_LIST_STRUCTURE(
                 returned_objects_string, next_string)
     dialog = ObjectLostAndFoundService.OBJECTS_RETURN_MESSAGE_DIALOG(
         services.active_sim_info())
     dialog.show_dialog(additional_tokens=(returned_objects_string, ))
Example #4
0
    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
Example #5
0
 def get_definition_notebook_data(self, ingredient_cache=[]):
     ingredients_used = {}
     recipe_definition = self.get_recipe_definition()
     if recipe_definition is None or self.final_product is None:
         return
     ingredient_display = []
     if recipe_definition.use_ingredients is not None:
         for tuned_ingredient_factory in recipe_definition.sorted_ingredient_requirements:
             ingredients_found_count = 0
             ingredients_needed_count = 0
             ingredient_requirement = tuned_ingredient_factory()
             ingredient_requirement.attempt_satisfy_ingredients(
                 ingredient_cache, ingredients_used)
             ingredients_found_count += ingredient_requirement.count_satisfied
             ingredients_needed_count += ingredient_requirement.count_required
             ingredient_display.append(
                 SubListData(None, ingredients_found_count,
                             ingredients_needed_count, True, False,
                             ingredient_requirement.get_diplay_name(), None,
                             None))
     return EntryData(
         LocalizationHelperTuning.get_object_name(self.final_product),
         IconInfoData(obj_def_id=self.final_product.id),
         self._get_entry_tooltip(self.final_product), ingredient_display,
         self.entry_sublist_is_sortable)
Example #6
0
 def _do_behavior(self):
     royalty_payment = self.royalty_payment
     recipient = self.interaction.get_participant(
         royalty_payment.royalty_recipient)
     if recipient is None:
         logger.error(
             "Trying to set up a royalty payment but interaction, {}, doesn't have the participant type {}.",
             self.interaction, royalty_payment.royalty_recipient)
     royalty_tracker = recipient.sim_info.royalty_tracker
     if royalty_tracker is None:
         logger.error(
             'Trying to set up a royalty payment but the sim has a None royalty tracker.'
         )
     participant = self.interaction.get_participant(
         royalty_payment.royalty_subject)
     if participant is None:
         logger.error(
             "Trying to set up a royalty payment but the royalty subject, {}, doesn't exist in this interaction.",
             royalty_payment.royalty_subject)
     if isinstance(participant, (str, LocalizedString)):
         display_name = LocalizationHelperTuning.get_raw_text(participant)
     else:
         display_name = LocalizationHelperTuning.get_object_name(
             participant)
     royalty_tracker.start_royalty(
         royalty_payment.royalty_type, royalty_payment.guid64, display_name,
         royalty_payment.payment_multipliers.get_multiplier(
             self.interaction.get_resolver()))
Example #7
0
 def _get_entry_tooltip(self, entry_def):
     return EntryTooltip(
         HovertipStyle.HOVER_TIP_DEFAULT, {
             TooltipFields.recipe_name:
             LocalizationHelperTuning.get_object_name(entry_def),
             TooltipFields.recipe_description:
             LocalizationHelperTuning.get_object_description(entry_def)
         })
 def root_stock_name_list(self):
     if not self._fruit_spawners:
         return
     name_list = []
     for spawner in self._fruit_spawners:
         tree_fruit_name = spawner.main_spawner.cls._components.gardening_component._tuned_values.fruit_name
         while tree_fruit_name not in name_list:
             name_list.append(tree_fruit_name)
     for (index, name) in enumerate(name_list):
         name_list[index] = LocalizationHelperTuning.get_object_name(_SplicedFruitData(name))
     return name_list
Example #9
0
 def root_stock_name_list(self):
     if not self._fruit_spawners:
         return
     name_list = []
     for spawner in self._fruit_spawners:
         tree_fruit_name = spawner.main_spawner.cls._components.gardening_component._tuned_values.fruit_name
         while tree_fruit_name not in name_list:
             name_list.append(tree_fruit_name)
     for (index, name) in enumerate(name_list):
         name_list[index] = LocalizationHelperTuning.get_object_name(
             _SplicedFruitData(name))
     return name_list
Example #10
0
 def _ui_metadata_gen(self):
     additional_information = self._get_additional_information()
     if additional_information and self.show_gardening_details():
         additional_information.sort()
         object_info_names = []
         object_info_descriptions = []
         bullet_points = []
         for (_, name, value) in additional_information:
             object_info_names.append(name)
             object_info_descriptions.append(value)
             bullet_point = LocalizationHelperTuning.get_name_value_pair(
                 name, value)
             bullet_points.append(bullet_point)
         description = LocalizationHelperTuning.get_bulleted_list(
             None, *bullet_points)
         plant_name = LocalizationHelperTuning.get_object_name(
             self.owner.definition)
     else:
         object_info_names = None
         object_info_descriptions = None
         if GardeningTuning.is_spliced(self.owner):
             description = self._spliced_description
             plant_name = GardeningTuning.SPLICED_PLANT_NAME()
         else:
             if GardeningTuning.is_shoot(
                     self.owner) and self.root_stock is not None:
                 description = LocalizationHelperTuning.get_object_name(
                     self.root_stock.main_spawner)
             else:
                 description = LocalizationHelperTuning.get_object_description(
                     self.owner.definition)
             plant_name = LocalizationHelperTuning.get_object_name(
                 self.owner.definition)
     subtext = self.owner.get_state_strings()
     yield ('object_info_names', object_info_names)
     yield ('object_info_descriptions', object_info_descriptions)
     yield ('recipe_name', plant_name)
     yield ('recipe_description', description)
     if subtext is not None:
         yield ('subtext', subtext)
 def get_definition_notebook_data(self, ingredient_cache=()):
     definition_manager = services.definition_manager()
     fruit_definition = definition_manager.get(
         self.entry_object_definition_id)
     if fruit_definition is None:
         return
     gardening_tuned_values = fruit_definition.cls._components.gardening._tuned_values
     plant_definition = gardening_tuned_values.plant
     sub_list_data = []
     sub_list_data.append(
         SubListData(None, 0, 0, True, False,
                     self.entry_text_value(fruit_definition.price / 5),
                     None, None))
     season_service = services.season_service()
     if season_service is not None:
         season_text = GardeningTuning.get_seasonality_text_from_plant(
             plant_definition)
         if season_text is None:
             season_text = GardeningTuning.PLANT_SEASONALITY_TEXT(
                 GardeningTuning.SEASONALITY_ALL_SEASONS_TEXT)
         sub_list_data.append(
             SubListData(None, 0, 0, True, False, season_text, None, None))
     sub_list_data.append(
         SubListData(
             None, 0, 0, True, False,
             LocalizationHelperTuning.get_object_description(
                 plant_definition), None, None))
     for (splice_fruit, splice_fruit_result
          ) in gardening_tuned_values.splicing_recipies.items():
         sub_list_data.append(
             SubListData(
                 None, 0, 0, True, False,
                 self.entry_text_splicing(splice_fruit,
                                          splice_fruit_result), None, None))
     gardening_collection_data = ObjectCollectionData.get_collection_data(
         CollectionIdentifier.Gardening)
     for obj_data in itertools.chain(
             gardening_collection_data.object_list,
             gardening_collection_data.bonus_object_list):
         if obj_data.collectable_item is fruit_definition:
             rarity_text = ObjectCollectionData.COLLECTION_RARITY_MAPPING[
                 obj_data.rarity].text_value
             sub_list_data.append(
                 SubListData(None, 0, 0, True, False,
                             self.entry_text_rarity(rarity_text), None,
                             None))
             break
     entry_data = EntryData(
         LocalizationHelperTuning.get_object_name(fruit_definition),
         IconInfoData(obj_def_id=fruit_definition.id), None, sub_list_data,
         None)
     return entry_data
Example #12
0
 def create_row(cls, inst, row_obj, context=DEFAULT, target=DEFAULT):
     inst_or_cls = inst if inst is not None else cls
     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,
         name=LocalizationHelperTuning.get_object_name(row_obj))
     inst_or_cls._test_continuation(row, context=context, target=target)
     return row
Example #13
0
 def get_root_stock_names(self):
     fruit_names = []
     for spawner in self._fruit_spawners:
         if spawner.spawn_weight == 0:
             continue
         tree_fruit_name_key = spawner.main_spawner.cls._components.gardening._tuned_values.fruit_name.hash
         if tree_fruit_name_key not in fruit_names:
             fruit_names.append(tree_fruit_name_key)
     localized_fruit_names = []
     for fruit_name in fruit_names:
         localized_fruit_names.append(
             LocalizationHelperTuning.get_object_name(
                 _SplicedFruitData(fruit_name)))
     return localized_fruit_names
 def _get_fish_caught_text(self, fish_caught):
     all_fish_strings = []
     for fish in fish_caught:
         type_loc_string = LocalizationHelperTuning.get_object_name(
             fish.definition)
         value_loc_string = LocalizationHelperTuning.get_money(
             fish.current_value)
         weight_loc_string = fish.get_localized_weight()
         fish_data_text = self.fish_information_text(
             weight_loc_string, type_loc_string, value_loc_string)
         all_fish_strings.append(fish_data_text)
     final_fish_text = LocalizationHelperTuning.get_bulleted_list(
         self.fish_header_text(), *all_fish_strings)
     return final_fish_text
 def _do_behavior(self):
     royalty_payment = self.royalty_payment
     recipient = self.interaction.get_participant(royalty_payment.royalty_recipient)
     if recipient is None:
         logger.error("Trying to set up a royalty payment but interaction, {}, doesn't have the participant type {}.", self.interaction, royalty_payment.royalty_recipient)
     royalty_tracker = recipient.sim_info.royalty_tracker
     if royalty_tracker is None:
         logger.error('Trying to set up a royalty payment but the sim has a None royalty tracker.')
     participant = self.interaction.get_participant(royalty_payment.royalty_subject)
     if participant is None:
         logger.error("Trying to set up a royalty payment but the royalty subject, {}, doesn't exist in this interaction.", royalty_payment.royalty_subject)
     if isinstance(participant, (str, LocalizedString)):
         display_name = LocalizationHelperTuning.get_raw_text(participant)
     else:
         display_name = LocalizationHelperTuning.get_object_name(participant)
     royalty_tracker.start_royalty(royalty_payment.royalty_type, royalty_payment.guid64, display_name, royalty_payment.payment_multipliers.get_multiplier(self.interaction.get_resolver()))
Example #16
0
 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
Example #17
0
 def _fill_notebook_entry_data(self, notebook_subcategory_message, subcategory_tuning, entry, entry_def_id, definition_based, new_entry):
     active_sim = self._owner.get_sim_instance(allow_hidden_flags=ALL_HIDDEN_REASONS)
     with ProtocolBufferRollback(notebook_subcategory_message.entries) as notebook_entry_message:
         notebook_entry_message.entry_message = entry.entry_text
         if entry_def_id is not None:
             notebook_entry_message.entry_id = entry_def_id
         if entry.entry_icon_info_data is not None:
             notebook_entry_message.entry_icon = create_icon_info_msg(entry.entry_icon_info_data)
         if entry.entry_tooltip is not None:
             notebook_entry_message.entry_metadata_hovertip.hover_tip = entry.entry_tooltip.tooltip_style
             for (tooltip_key, tooltip_text) in entry.entry_tooltip.tooltip_fields.items():
                 setattr(notebook_entry_message.entry_metadata_hovertip, tooltip_key.name, tooltip_text)
         notebook_entry_message.new_entry = new_entry
         if entry.entry_sublist:
             entry_list_description = subcategory_tuning.entry_list_texts.has_list_text
             if entry_list_description is not None:
                 notebook_entry_message.entry_list_description = entry_list_description
             if entry.entry_sublist_is_sortable is None:
                 notebook_entry_message.is_sortable = False
                 notebook_entry_message.is_new_item_sortable = False
             else:
                 notebook_entry_message.is_sortable = True
                 notebook_entry_message.is_new_item_sortable = entry.entry_sublist_is_sortable.include_new_entry
             for sublist_data in entry.entry_sublist:
                 with ProtocolBufferRollback(notebook_entry_message.entry_list) as notebook_entry_list_message:
                     if sublist_data.is_ingredient:
                         item_message = sublist_data.object_display_name
                     else:
                         item_message = LocalizationHelperTuning.get_object_name(sublist_data.object_definition)
                     notebook_entry_list_message.item_message = item_message
                     if active_sim is not None and sublist_data.num_objects_required > 0:
                         if sublist_data.is_ingredient:
                             notebook_entry_list_message.item_count = sublist_data.item_count
                         else:
                             notebook_entry_list_message.item_count = active_sim.inventory_component.get_count(sublist_data.object_definition)
                     else:
                         notebook_entry_list_message.item_count = 0
                     notebook_entry_list_message.item_total = sublist_data.num_objects_required
                     notebook_entry_list_message.new_item = sublist_data.new_item
                     if sublist_data.item_icon_info_data is not None:
                         notebook_entry_list_message.item_icon = create_icon_info_msg(sublist_data.item_icon_info_data)
                     if sublist_data.item_tooltip is not None:
                         notebook_entry_list_message.item_tooltip = sublist_data.item_tooltip
         else:
             entry_list_description = subcategory_tuning.entry_list_texts.no_list_text
             if entry_list_description is not None:
                 notebook_entry_message.entry_list_description = entry_list_description
Example #18
0
 def get_definition_notebook_data(self, ingredient_cache=[]):
     definition_manager = services.definition_manager()
     snippet_manager = services.snippet_manager()
     fish_definition = definition_manager.get(
         self.entry_object_definition_id)
     sublist = []
     for (sub_entry_id, new_sub_entry) in reversed(self.sub_entries):
         bait_data = snippet_manager.get(sub_entry_id)
         if fish_definition is None or bait_data is None:
             return
         sublist.append(
             SubListData(
                 None, 0, 0, True, new_sub_entry, bait_data.bait_name(),
                 IconInfoData(obj_def_id=bait_data.bait_icon_definition.id),
                 bait_data.bait_description()))
     return EntryData(
         LocalizationHelperTuning.get_object_name(fish_definition),
         IconInfoData(obj_def_id=fish_definition.id),
         self._get_entry_tooltip(fish_definition), sublist,
         self.entry_sublist_is_sortable)
Example #19
0
 def _handle_parented_objects(self, obj):
     objects_in_household_inventory = []
     for child_obj in tuple(obj.children):
         if self._allow_destruction_on_inventory_transfer(child_obj):
             child_obj.destroy(source=self.owner,
                               cause='Parent is being inventoried.')
         else:
             if self.player_try_add_object(child_obj):
                 continue
             if build_buy.move_object_to_household_inventory(child_obj):
                 objects_in_household_inventory.append(child_obj)
             else:
                 world_obj = self.owner
                 fgl_context_fn = create_fgl_context_for_object if world_obj.is_on_active_lot(
                 ) else create_fgl_context_for_object_off_lot
                 fgl_starting_location = create_starting_location(
                     position=world_obj.position)
                 (translation, orientation) = find_good_location(
                     fgl_context_fn(fgl_starting_location, child_obj))
                 if translation is not None and orientation is not None:
                     child_obj.set_parent(
                         None,
                         transform=sims4.math.Transform(
                             translation, orientation),
                         routing_surface=world_obj.routing_surface)
                 else:
                     child_obj.destroy(
                         source=self.owner,
                         cause=
                         "Parent is being inventoried and object can't be placed anywhere."
                     )
     if objects_in_household_inventory and self.PARENTED_OBJECT_MOVED_TO_HOUSEHOLD_INVENTORY_NOTIFICATION is not None:
         sim_info = self.owner.sim_info if self.owner.is_sim else services.active_sim_info(
         )
         notification = self.PARENTED_OBJECT_MOVED_TO_HOUSEHOLD_INVENTORY_NOTIFICATION(
             sim_info, resolver=SingleObjectResolver(obj))
         notification.show_dialog(
             additional_tokens=(LocalizationHelperTuning.get_bulleted_list(
                 None,
                 *(LocalizationHelperTuning.get_object_name(obj)
                   for obj in objects_in_household_inventory)), ))
Example #20
0
 def factory(candidate_ingredients, ingredient_ref):
     for ingredient in candidate_ingredients:
         while ingredient.id == ingredient_ref.id:
             return ([ingredient], None, LocalizationHelperTuning.get_object_name(ingredient_ref))
     return ([], None, LocalizationHelperTuning.get_object_name(ingredient_ref))
 def get_diplay_name(self):
     return LocalizationHelperTuning.get_object_name(self._definition)
 def _get_display_text(self):
     return LocalizationHelperTuning.get_object_name(self._definition)
Example #23
0
 def _get_display_text(self, resolver=None):
     return LocalizationHelperTuning.get_object_name(self._definition)
Example #24
0
 def get_icon_info_data(self):
     return IconInfoData(obj_instance=self, obj_def_id=self.definition.id, obj_geo_hash=self.geometry_state, obj_material_hash=self.material_hash, obj_name=LocalizationHelperTuning.get_object_name(self))
 def _get_treasure_caught_text(self, treasure_caught):
     treasure_string = LocalizationHelperTuning.get_bulleted_list(
         self.treasure_header_text(),
         *(LocalizationHelperTuning.get_object_name(treasure)
           for treasure in treasure_caught))
     return treasure_string
Example #26
0
 def _populate_spell_entry_message(self, entry_message, spell):
     entry_message.name = spell.display_name
     if spell.locked_description and not self._is_unlocked(spell):
         entry_message.description = spell.locked_description
     else:
         entry_message.description = spell.display_description
     entry_message.icon.type = spell.display_icon.type
     entry_message.icon.group = spell.display_icon.group
     entry_message.icon.instance = spell.display_icon.instance
     ingredients = spell.ingredients.ingredients
     if ingredients:
         entry_message.subtext_title = SpellbookTuning.INGREDIENTS_LABEL
         entry_message.subtext = LocalizationHelperTuning.get_comma_separated_list(*tuple(SpellbookTuning.INGREDIENT_FORMAT(LocalizationHelperTuning.get_object_name(ingredient.ingredient), ingredient.quantity) for ingredient in ingredients))