Beispiel #1
0
	def IsAvailable (self, targetSimInfo: sim_info.SimInfo) -> bool:
		"""
		Get whether or not the target sim can use this safety method. This may incorrectly return false for non-instanced sims; we cannot read the inventory
		of sims not instanced.
		"""

		if not isinstance(targetSimInfo, sim_info.SimInfo):
			raise Exceptions.IncorrectTypeException(targetSimInfo, "targetSimInfo", (sim_info.SimInfo,))

		if not self.HasRequirement:
			return True

		if not targetSimInfo.is_instanced():
			return False

		targetSim = targetSimInfo.get_sim_instance()  # type: sim.Sim

		for requirementGroup in self.Requirements:  # type: typing.Tuple[WoohooSafetyMethod.Requirement, ...]
			if len(requirementGroup) == 0:
				continue

			groupRequirementsMet = True  # type: bool

			for requirement in requirementGroup:  # type: WoohooSafetyMethod.Requirement
				if not requirement.RequirementMet(targetSim):
					groupRequirementsMet = False
					break

			if groupRequirementsMet:
				return True

		return False
Beispiel #2
0
    def generate_outfit(
            sim_info: SimInfo, outfit_category_and_index: Tuple[OutfitCategory,
                                                                int]) -> bool:
        """generate_outfit(sim_info, outfit_category_and_index)

        Generate an outfit for a Sim for the specified OutfitCategory and Index.

        .. note:: If an outfit exists in the specified OutfitCategory and Index, already, it will be overridden.

        :param sim_info: The Sim to generate an outfit for.
        :type sim_info: SimInfo
        :param outfit_category_and_index: The OutfitCategory and Index of the outfit to generate.
        :type outfit_category_and_index: Tuple[OutfitCategory, int]
        :return: True, if an outfit was generated successfully. False, if not.
        :rtype: bool
        """
        try:
            sim_info.on_outfit_generated(
                sim_info, CommonOutfitUtils.get_current_outfit(sim_info))
            sim_info.generate_outfit(*outfit_category_and_index)
            return True
        except Exception as ex:
            CommonExceptionHandler.log_exception(
                ModInfo.get_identity().name,
                'Problem occurred running function \'{}\'.'.format(
                    CommonOutfitUtils.generate_outfit.__name__),
                exception=ex)
        return False
 def set_outfit_clean(sim_info: SimInfo, outfit_category: OutfitCategory):
     """
         Flag the specified OutfitCategory of a sim as clean.
     :param sim_info: The sim to flag the OutfitCategory for.
     :param outfit_category: The OutfitCategory being flagged.
     """
     sim_info.clear_outfit_dirty(outfit_category)
 def set_outfit_dirty(sim_info: SimInfo, outfit_category: OutfitCategory):
     """
         Flag the specified OutfitCategory of a sim as dirty.
         This will tell the game that it needs to be updated.
     :param sim_info: The sim to flag the OutfitCategory for.
     :param outfit_category: The OutfitCategory being flagged.
     """
     sim_info.set_outfit_dirty(outfit_category)
 def update_outfits(sim_info: SimInfo):
     """
         Update all outfits of a sim.
     """
     sim_info.on_outfit_changed(
         sim_info, CommonOutfitUtils.get_current_outfit(sim_info))
     CommonOutfitUtils.resend_outfits(sim_info)
     sim_info.appearance_tracker.evaluate_appearance_modifiers()
 def set_current_outfit(sim_info: SimInfo,
                        outfit_category_and_index: Tuple[OutfitCategory,
                                                         int]):
     """
         Set the current outfit of a sim to the specified OutfitCategory and Index.
     :param sim_info: The sim to change the outfit of.
     :param outfit_category_and_index: The OutfitCategory and index to change to.
     """
     sim_info.set_current_outfit(outfit_category_and_index)
Beispiel #7
0
    def remove_previous_outfit(sim_info: SimInfo):
        """remove_previous_outfit(sim_info)

        Remove the outfit a Sim was wearing before their current outfit, from the cache.

        :param sim_info: The Sim to remove the outfit from.
        :type sim_info: SimInfo
        """
        sim_info.set_previous_outfit(None, force=True)
    def generate_outfit(sim_info: SimInfo,
                        outfit_category_and_index: Tuple[OutfitCategory, int]):
        """
            Generate an outfit for a sim for the specified OutfitCategory and Index.

            Note; If an outfit exists in the specified OutfitCategory and index, already, it will be overwritten.
        """
        sim_info.on_outfit_generated(
            sim_info, CommonOutfitUtils.get_current_outfit(sim_info))
        sim_info.generate_outfit(*outfit_category_and_index)
    def travel_to_lot(sim_info: SimInfo, lot_id: int):
        """travel_to_lot(sim_info, lot_id)

        Travel with the specified Sim to the Lot with the specified identifier.

        :param sim_info: The Sim to travel with.
        :type sim_info: SimInfo
        :param lot_id: The identifier of the lot to travel to.
        :type lot_id: int
        """
        sim_info.send_travel_switch_to_zone_op(zone_id=lot_id)
    def travel_to_zone(sim_info: SimInfo, zone_id: int):
        """travel_to_zone(sim_info, zone_id)

        Travel with the specified Sim to a Zone.

        :param sim_info: The Sim to travel with.
        :type sim_info: SimInfo
        :param zone_id: The identifier of the zone to travel to.
        :type zone_id: int
        """
        sim_info.send_travel_switch_to_zone_op(zone_id=zone_id)
Beispiel #11
0
    def resend_outfits(sim_info: SimInfo) -> bool:
        """resend_outfits(sim_info)

        Resend outfit data to a Sim to refresh their outfits.

        :param sim_info: The Sim to resend the outfit for.
        :type sim_info: SimInfo
        :return: True, if outfits were resent successfully. False, if not.
        :rtype: bool
        """
        sim_info.resend_outfits()
        return True
Beispiel #12
0
    def set_age(sim_info: SimInfo, age: Union[Age, int]) -> bool:
        """set_age(sim_info, age)

        Set the Age of a Sim.

        :param sim_info: The Sim to set the Age of.
        :type sim_info: SimInfo
        :param age: The Age to set the Sim to.
        :type age: Union[Age, int]
        :return: True, if the Age was set successfully. False, if not.
        :rtype: bool
        """
        sim_info.apply_age(age)
        return True
Beispiel #13
0
 def set_age(sim_info: SimInfo, age: Union[Age, int]) -> bool:
     """
         Set the Age of a sim.
     """
     try:
         sim_info.apply_age(age)
         return True
     except Exception as ex:
         CommonExceptionHandler.log_exception(
             ModInfo.get_identity().name,
             'Failed to set age of sim {} to {}.'.format(
                 pformat(sim_info), age),
             exception=ex)
         return False
Beispiel #14
0
    def update_outfits(sim_info: SimInfo) -> bool:
        """update_outfits(sim_info)

        Update all outfits of a Sim.

        :param sim_info: The Sim to update outfits for.
        :type sim_info: SimInfo
        :return: True, if the outfits were updated successfully. False, if not.
        :rtype: bool
        """
        sim_info.on_outfit_changed(
            sim_info, CommonOutfitUtils.get_current_outfit(sim_info))
        CommonOutfitUtils.resend_outfits(sim_info)
        sim_info.appearance_tracker.evaluate_appearance_modifiers()
        return True
Beispiel #15
0
 def get_traits(sim_info: SimInfo) -> List[Trait]:
     """
         Retrieve all Traits of a sim.
     """
     if not hasattr(sim_info, 'get_traits'):
         return list()
     return list(sim_info.get_traits())
Beispiel #16
0
    def add_buff(
        sim_info: SimInfo,
        *buff_ids: Union[int, CommonBuffId],
        buff_reason: Union[int, str, LocalizedString, CommonStringId] = None
    ) -> bool:
        """add_buff(sim_info, *buff_ids, buff_reason=None)

        Add the specified buffs to a sim.

        :param sim_info: The sim to add the specified buffs to.
        :type sim_info: SimInfo
        :param buff_ids: The decimal identifiers of buffs to add.
        :type buff_ids: int
        :param buff_reason: The text that will display when the player hovers over the buffs. What caused the buffs to be added.
        :type buff_reason: Union[int, str, LocalizedString, CommonStringId], optional
        :return: True, if all of the specified buffs were successfully added. False, if not.
        :rtype: bool
        """
        if sim_info is None:
            raise AssertionError('Argument sim_info was None')
        if not CommonComponentUtils.has_component(sim_info,
                                                  CommonComponentType.BUFF):
            return False
        localized_buff_reason = CommonLocalizationUtils.create_localized_string(
            buff_reason)
        success = True
        for buff_identifier in buff_ids:
            buff_instance = CommonBuffUtils.load_buff_by_id(buff_identifier)
            if buff_instance is None:
                continue
            if not sim_info.add_buff_from_op(
                    buff_instance, buff_reason=localized_buff_reason):
                success = False
        return success
Beispiel #17
0
    def get_outfit_parts(
        sim_info: SimInfo,
        outfit_category_and_index: Union[Tuple[OutfitCategory, int],
                                         None] = None
    ) -> Dict[BodyType, int]:
        """get_outfit_parts(sim_info, outfit_category_and_index=None)

        Retrieve Outfit Parts for the specified OutfitCategory and Index of a Sim.

        :param sim_info: The Sim to retrieve outfit parts of.
        :type sim_info: SimInfo
        :param outfit_category_and_index: The OutfitCategory and Index of the outfit to retrieve data from. Default is the current outfit.
        :type outfit_category_and_index: Union[Tuple[OutfitCategory, int], None], optional
        :return: A dictionary of body types and cas parts in those body types for the outfit of a Sim.
        :rtype: Dict[BodyType, int]
        """
        if outfit_category_and_index is None:
            outfit_category_and_index = CommonOutfitUtils.get_current_outfit(
                sim_info)
        outfit_data = sim_info.get_outfit(outfit_category_and_index[0],
                                          outfit_category_and_index[1])
        if outfit_data is None:
            return dict()
        return dict(
            zip(list(outfit_data.body_types), list(outfit_data.part_ids)))
    def delete_sim(sim_info: SimInfo, cause: str = None) -> bool:
        """delete_sim(sim_info, cause=None)

        Delete a Sim.

        :param sim_info: The Sim to delete.
        :type sim_info: SimInfo
        :param cause: The reason for the deletion.
        :type cause: str, optional
        :return: True, if the Sim was deleted successfully. False, if not.
        :rtype: bool
        """
        if not CommonSimSpawnUtils.despawn_sim(sim_info, cause=cause):
            return False
        sim_info.remove_permanently()
        return True
    def resend_outfits(sim_info: SimInfo) -> bool:
        """resend_outfits(sim_info)

        Resend outfit data to a Sim to refresh their outfits.

        :param sim_info: The Sim to resend the outfit for.
        :type sim_info: SimInfo
        :return: True, if outfits were resent successfully. False, if not.
        :rtype: bool
        """
        try:
            sim_info.resend_outfits()
            return True
        except Exception as ex:
            CommonExceptionHandler.log_exception(ModInfo.get_identity(), 'Problem occurred running function \'{}\'.'.format(CommonOutfitUtils.resend_outfits.__name__), exception=ex)
        return False
Beispiel #20
0
    def remove_buff(sim_info: SimInfo, *buff_ids: Union[int,
                                                        CommonBuffId]) -> bool:
        """remove_buff(sim_info, *buff_ids)

        Remove the specified buffs from a sim.

        :param sim_info: The sim to remove the specified buffs from.
        :type sim_info: SimInfo
        :param buff_ids: The decimal identifiers of Buffs to remove.
        :type buff_ids: int
        :return: True, if all of the specified buffs were successfully removed. False, if not.
        :rtype: bool
        """
        if sim_info is None:
            raise AssertionError('Argument sim_info was None')
        if not CommonComponentUtils.has_component(sim_info,
                                                  CommonComponentType.BUFF):
            return False
        success = True
        for buff_identifier in buff_ids:
            buff_instance = CommonBuffUtils.load_buff_by_id(buff_identifier)
            if buff_instance is None:
                continue
            if not sim_info.remove_buff_by_type(buff_instance):
                success = False
        return success
    def remove_buff(sim_info: SimInfo, *buff_ids: int) -> bool:
        """remove_buff(sim_info, *buff_ids)

        Remove the specified buffs from a sim.

        :param sim_info: The sim to remove the specified buffs from.
        :type sim_info: SimInfo
        :param buff_ids: The decimal identifiers of Buffs to remove.
        :type buff_ids: int
        :return: True, if all of the specified buffs were successfully removed. False, if not.
        :rtype: bool
        """
        if sim_info is None:
            CommonExceptionHandler.log_exception(ModInfo.get_identity().name, 'Argument \'sim_info\' was \'None\' for \'{}\' of class \'{}\''.format(CommonBuffUtils.remove_buff.__name__, CommonBuffUtils.__name__))
            return False
        if not CommonComponentUtils.has_component(sim_info, CommonComponentType.BUFF):
            return False
        success = True
        for buff_identifier in buff_ids:
            buff_instance = CommonBuffUtils._load_buff_instance(buff_identifier)
            if buff_instance is None:
                continue
            if not sim_info.remove_buff_by_type(buff_instance):
                success = False
        return success
    def add_buff(sim_info: SimInfo, *buff_ids: int, buff_reason: Union[int, str, LocalizedString]=None) -> bool:
        """add_buff(sim_info, *buff_ids, buff_reason=None)

        Add the specified buffs to a sim.

        :param sim_info: The sim to add the specified buffs to.
        :type sim_info: SimInfo
        :param buff_ids: The decimal identifiers of buffs to add.
        :type buff_ids: int
        :param buff_reason: The text that will display when the player hovers over the buffs. What caused the buffs to be added.
        :type buff_reason: Union[int, str, LocalizedString], optional
        :return: True, if all of the specified buffs were successfully added. False, if not.
        :rtype: bool
        """
        if sim_info is None:
            CommonExceptionHandler.log_exception(ModInfo.get_identity().name, 'Argument \'sim_info\' was \'None\' for \'{}\' of class \'{}\''.format(CommonBuffUtils.add_buff.__name__, CommonBuffUtils.__name__))
            return False
        if not CommonComponentUtils.has_component(sim_info, CommonComponentType.BUFF):
            return False
        localized_buff_reason = CommonLocalizationUtils.create_localized_string(buff_reason)
        success = True
        for buff_identifier in buff_ids:
            buff_instance = CommonBuffUtils._load_buff_instance(buff_identifier)
            if buff_instance is None:
                continue
            if not sim_info.add_buff_from_op(buff_instance, buff_reason=localized_buff_reason):
                success = False
        return success
    def swap_gender(sim_info: SimInfo, update_gender_options: bool=True) -> bool:
        """swap_gender(sim_info, update_gender_options=True)

        Swap the Gender of a Sim to it's opposite. i.e. Change a Sim from Male to Female or from Female to Male.

        :param sim_info: An instance of a Sim.
        :type sim_info: SimInfo
        :param update_gender_options: If True, gender option traits such as Toilet Usage, Clothing Preference, Pregnancy, and Body Frame will be updated to reflect the vanilla settings for each gender\
        For example, if a Human Sim is swapping from Female to Male, their gender options will be updated to Toilet Standing, Cannot Be Impregnated, Can Impregnate, Mens Wear clothing preference, and Masculine Frame.\
        If False, gender option traits will not be updated.\
        Default is True.
        :type update_gender_options: bool, optional
        :return: True, if the Gender of the Sim was swapped successfully. False, if not.
        :rtype: bool
        """
        from sims4communitylib.utils.sims.common_sim_gender_option_utils import CommonSimGenderOptionUtils
        result = False
        frame = CommonSimGenderOptionUtils.has_masculine_frame(sim_info)
        prefers_menswear = CommonSimGenderOptionUtils.prefers_menswear(sim_info)
        can_impregnate = CommonSimGenderOptionUtils.can_impregnate(sim_info)
        can_be_impregnated = CommonSimGenderOptionUtils.can_be_impregnated(sim_info)
        can_reproduce = CommonSimGenderOptionUtils.can_reproduce(sim_info)
        uses_toilet_standing = CommonSimGenderOptionUtils.uses_toilet_standing(sim_info)
        has_breasts = CommonSimGenderOptionUtils.has_breasts(sim_info)
        saved_outfits = sim_info.save_outfits()
        current_outfit = CommonOutfitUtils.get_current_outfit(sim_info)
        if CommonGenderUtils.is_male(sim_info):
            result = CommonGenderUtils.set_gender(sim_info, Gender.FEMALE)
            if update_gender_options:
                CommonSimGenderOptionUtils.update_gender_options_to_vanilla_female(sim_info)
        elif CommonGenderUtils.is_female(sim_info):
            result = CommonGenderUtils.set_gender(sim_info, Gender.MALE)
            if update_gender_options:
                CommonSimGenderOptionUtils.update_gender_options_to_vanilla_male(sim_info)
        if not update_gender_options:
            CommonSimGenderOptionUtils.update_body_frame(sim_info, frame)
            CommonSimGenderOptionUtils.update_clothing_preference(sim_info, prefers_menswear)
            CommonSimGenderOptionUtils.update_can_impregnate(sim_info, can_impregnate)
            CommonSimGenderOptionUtils.update_can_be_impregnated(sim_info, can_be_impregnated)
            CommonSimGenderOptionUtils.update_can_reproduce(sim_info, can_reproduce)
            CommonSimGenderOptionUtils.update_toilet_usage(sim_info, uses_toilet_standing)
            CommonSimGenderOptionUtils.update_has_breasts(sim_info, has_breasts)
            sim_info.load_outfits(saved_outfits)
            CommonOutfitUtils.resend_outfits(sim_info)
            CommonOutfitUtils.set_current_outfit(sim_info, current_outfit)
        return result
    def update_outfits(sim_info: SimInfo) -> bool:
        """update_outfits(sim_info)

        Update all outfits of a Sim.

        :param sim_info: The Sim to update outfits for.
        :type sim_info: SimInfo
        :return: True, if the outfits were updated successfully. False, if not.
        :rtype: bool
        """
        try:
            sim_info.on_outfit_changed(sim_info, CommonOutfitUtils.get_current_outfit(sim_info))
            CommonOutfitUtils.resend_outfits(sim_info)
            sim_info.appearance_tracker.evaluate_appearance_modifiers()
            return True
        except Exception as ex:
            CommonExceptionHandler.log_exception(ModInfo.get_identity(), 'Problem occurred running function \'{}\'.'.format(CommonOutfitUtils.update_outfits.__name__), exception=ex)
        return False
Beispiel #25
0
    def delete_sim(sim_info: SimInfo, source: str=None, cause: str=None, **kwargs) -> bool:
        """delete_sim(sim_info, source=None, cause=None, **kwargs)

        Delete a Sim.

        :param sim_info: The Sim to delete.
        :type sim_info: SimInfo
        :param source: The source of the destruction. Default is None.
        :type source: str, optional
        :param cause: The cause of the destruction. Default is None.
        :type cause: str, optional
        :return: True, if the Sim was deleted successfully. False, if not.
        :rtype: bool
        """
        if not CommonSimSpawnUtils.despawn_sim(sim_info, source=source, cause=cause, **kwargs):
            return False
        sim_info.remove_permanently()
        return True
Beispiel #26
0
def GetLastSimID(targetSimInfo: sim_info.SimInfo) -> typing.Optional[int]:
    if not isinstance(targetSimInfo, sim_info.SimInfo):
        Exceptions.IncorrectTypeException(targetSimInfo, "targetSimInfo",
                                          (sim_info.SimInfo, ))

    lastSimIDStatisticType = services.get_instance_manager(
        resources.Types.STATISTIC).get(
            LastSimIDStatisticID,
            None)  # type: typing.Optional[typing.Type[statistic.Statistic]]

    if lastSimIDStatisticType is None:
        Debug.Log(
            "Could not find the last sim id statistic type.\nTarget Sim ID: %s"
            % str(targetSimInfo.id),
            This.Mod.Namespace,
            Debug.LogLevels.Error,
            group=This.Mod.Namespace,
            owner=__name__,
            lockIdentifier=__name__ + ":MissingLastSimIDStatisticType")
        return None

    lastSimIDStatisticTracker = targetSimInfo.get_tracker(
        lastSimIDStatisticType
    )  # type: typing.Optional[statistic_tracker.StatisticTracker]

    if lastSimIDStatisticTracker is None:
        Debug.Log(
            "Could not find the last sim id statistic's tracker in the target sim.\nTarget Sim ID: %s"
            % str(targetSimInfo.id),
            This.Mod.Namespace,
            Debug.LogLevels.Error,
            group=This.Mod.Namespace,
            owner=__name__,
            lockIdentifier=__name__ + ":MissingLastSimIDStatisticTracker")
        return None

    lastSimIDStatistic = lastSimIDStatisticTracker.get_statistic(
        lastSimIDStatisticType,
        add=True)  # type: typing.Optional[statistic.Statistic]

    if lastSimIDStatistic is None:
        Debug.Log(
            "Could not retrieve a sim's last sim id statistic\nTarget Sim ID: %s"
            % str(targetSimInfo.id),
            This.Mod.Namespace,
            Debug.LogLevels.Error,
            group=This.Mod.Namespace,
            owner=__name__,
            lockIdentifier=__name__ + ":MissingLastSimIDStatistic")
        return None

    lastSimID = lastSimIDStatistic.get_value()  # type: int

    if lastSimID == 0:
        return None
    else:
        return lastSimID
 def has_outfit(
         sim_info: SimInfo, outfit_category_and_index: Tuple[OutfitCategory,
                                                             int]) -> bool:
     """
         Determine if a sim has an existing outfit in the specified OutfitCategory and Index.
     :param sim_info: The sim to check.
     :param outfit_category_and_index: The OutfitCategory and index to locate.
     """
     return sim_info.has_outfit(outfit_category_and_index)
Beispiel #28
0
 def get_buffs(cls, sim_info: SimInfo) -> List[Buff]:
     """
         Retrieve all buffs currently active on a sim.
     """
     if sim_info is None:
         CommonExceptionHandler.log_exception(ModInfo.get_identity().name, 'argument sim_info was \'None\' for {} of class {}'.format(CommonBuffUtils.get_buffs.__name__, CommonBuffUtils.__name__))
         return list()
     if not hasattr(sim_info, 'get_active_buff_types'):
         return list()
     return list(sim_info.get_active_buff_types())
Beispiel #29
0
 def set_gender(sim_info: SimInfo, gender: Union[int, Gender]) -> bool:
     """
         Set the Gender of a sim.
     """
     try:
         sim_info.gender = gender
         return True
     except Exception as ex:
         CommonExceptionHandler.log_exception(ModInfo.get_identity().name, 'Failed to set gender of Sim {} to {}.'.format(pformat(sim_info), gender), exception=ex)
         return False
    def get_current_mood(sim_info: SimInfo) -> Mood:
        """get_current_mood(sim_info)

        Retrieve the current mood for the specified Sim.

        :param sim_info: The Sim to retrieve the mood of.
        :type sim_info: SimInfo
        :return: The current Mood of the Sim.
        :rtype: Mood
        """
        return sim_info.get_mood()