Beispiel #1
0
 def _GetKeyText(self, setting: UISettingsShared.SettingStandardWrapper,
                 mod: Mods.Mod,
                 value: bool) -> localization.LocalizedString:
     keyTemplate = Language.String(This.Mod.Namespace +
                                   ".Mod_Settings.Values." + setting.Key +
                                   ".Key_Template")  # type: Language.String
     return keyTemplate.GetLocalizationString(mod.Name, mod.Author)
Beispiel #2
0
class SettingsList(UISettingsList.SettingsList):
    TitleStandard = Language.String(
        This.Mod.Namespace +
        ".Sim_Settings.List.Title")  # type: Language.String

    def _GetTitleText(self, listPath: str) -> localization.LocalizedString:
        return self._GetTitleStandardText()

    def _GetTitleStandardText(self) -> localization.LocalizedString:
        return self.TitleStandard.GetLocalizationString()

    def _GetTitleListPathText(self,
                              listPath: str) -> localization.LocalizedString:
        listPathIdentifier = listPath.replace(self.ListPathSeparator,
                                              "_")  # type: str
        fallbackText = "List.Paths." + listPathIdentifier + ".Title"  # type: str
        return Language.GetLocalizationStringByIdentifier(
            This.Mod.Namespace + ".Sim_Settings.List.Paths." +
            listPathIdentifier + ".Title",
            fallbackText=fallbackText)

    def _GetDescriptionText(self,
                            listPath: str) -> localization.LocalizedString:
        listPathIdentifier = listPath.replace(self.ListPathSeparator,
                                              "_")  # type: str
        return Language.GetLocalizationStringByIdentifier(
            This.Mod.Namespace + ".Sim_Settings.List.Paths." +
            listPathIdentifier + ".Description")
Beispiel #3
0
 def _GetValueText(self, setting: UISettingsShared.SettingStandardWrapper,
                   mod: Mods.Mod,
                   value: bool) -> localization.LocalizedString:
     valueTemplate = Language.String(
         This.Mod.Namespace + ".Mod_Settings.Values." + setting.Key +
         ".Value_Template")  # type: Language.String
     return valueTemplate.GetLocalizationString(
         Language.GetLocalizationStringByIdentifier(
             This.Mod.Namespace +
             ".Settings.Types.Boolean.Enabled_Disabled." + str(value),
             fallbackText=str(value)), str(mod.Distribution.UpdatesFileURL))
Beispiel #4
0
class ChoiceDialogButton(DialogButton):
    ChoiceButton = Language.String(
        This.Mod.Namespace + ".Setting_Dialogs.Choice_Button",
        fallbackText="Choice_Button")  # type: Language.String

    def __init__(self, selected: bool = False, *args, **kwargs):
        """
		:param selected: Whether or not the button's text will have a selected look.
		:type selected: bool
		"""

        super().__init__(*args, **kwargs)

        self.Selected = selected  # type: bool

    def GenerateDialogResponse(self) -> ui_dialog.UiDialogResponse:
        if self.Selected:
            valueButtonStringTokens = ("> ", self.Text, " <")
        else:
            valueButtonStringTokens = ("", self.Text, "")

        if self.ChoiceButton.IdentifierIsRegistered():
            buttonTextString = self.ChoiceButton.GetCallableLocalizationString(
                *valueButtonStringTokens)
        else:
            buttonTextString = self.Text

        responseArguments = {
            "dialog_response_id": self.ResponseID,
            "sort_order": self.SortOrder,
            "text": buttonTextString
        }

        if self.SubText is not None:
            responseArguments["subtext"] = self.SubText

        response = ui_dialog.UiDialogResponse(**responseArguments)

        return response
Beispiel #5
0
from __future__ import annotations

import abc
import traceback
import typing

import services
from NeonOcean.S4.Main import Debug, Language, This
from NeonOcean.S4.Main.Tools import Exceptions, TextBuilder
from NeonOcean.S4.Main.UI import Dialogs, Notifications, SettingsShared as UISettingsShared
from sims4 import collections, localization
from ui import ui_dialog, ui_dialog_generic, ui_dialog_notification, ui_dialog_picker, ui_text_input

InvalidInputNotificationTitle = Language.String(
    This.Mod.Namespace + ".Setting_Dialogs.Invalid_Input_Notification.Title"
)  # type: Language.String
InvalidInputNotificationText = Language.String(
    This.Mod.Namespace + ".Setting_Dialogs.Invalid_Input_Notification.Text"
)  # type: Language.String

PresetConfirmDialogTitle = Language.String(
    This.Mod.Namespace +
    ".Setting_Dialogs.Preset_Confirm_Dialog.Title")  # type: Language.String
PresetConfirmDialogText = Language.String(
    This.Mod.Namespace +
    ".Setting_Dialogs.Preset_Confirm_Dialog.Text")  # type: Language.String
PresetConfirmDialogYesButton = Language.String(
    This.Mod.Namespace + ".Setting_Dialogs.Preset_Confirm_Dialog.Yes_Button",
    fallbackText="Preset_Confirm_Dialog.Yes_Button")  # type: Language.String
PresetConfirmDialogNoButton = Language.String(
    This.Mod.Namespace + ".Setting_Dialogs.Preset_Confirm_Dialog.No_Button",
Beispiel #6
0
def _ShowInvalidLanguageNotification() -> None:
    notificationArguments = {
        "title":
        InvalidLanguageNotificationTitle.GetCallableLocalizationString(),
        "text":
        InvalidLanguageNotificationText.GetCallableLocalizationString(),
        "expand_behavior":
        ui_dialog_notification.UiDialogNotification.
        UiDialogNotificationExpandBehavior.FORCE_EXPAND,
        "urgency":
        ui_dialog_notification.UiDialogNotification.
        UiDialogNotificationUrgency.URGENT
    }

    Notifications.ShowNotification(**notificationArguments)


NoLocalizationPackagePacks = {Sims4Common.Pack.FP01
                              }  # type: typing.Set[Sims4Common.Pack]

InvalidLanguageNotificationTitle = MainLanguage.String(
    This.Mod.Namespace +
    ".Invalid_Language_Notification.Title")  # type: MainLanguage.String
InvalidLanguageNotificationText = MainLanguage.String(
    This.Mod.Namespace +
    ".Invalid_Language_Notification.Text")  # type: MainLanguage.String

_registeredLanguageHandlers = list(
)  # type: typing.List[typing.Type[LanguageHandlerBase]]
Beispiel #7
0
import time
import typing

from NeonOcean.S4.Main import Debug, Director, Language, Paths, LoadingShared, Reporting
from NeonOcean.S4.Main.Tools import Exceptions, Patcher, Python, Timer, Version
from NeonOcean.S4.Main.UI import Notifications
from NeonOcean.S4.Refer import GenderedLanguage, LanguageHandlers, This
from NeonOcean.S4.Refer.Tools import Package, STBL
from protocolbuffers import Localization_pb2
from server import client
import paths as Sims4Paths
from sims4 import common as Sims4Common, localization, resources
from ui import ui_dialog_notification

UnsupportedLanguageNotificationTitle = Language.String(
    This.Mod.Namespace +
    ".Warnings.Unsupported_Language.Title")  # type: Language.String
UnsupportedLanguageNotificationText = Language.String(
    This.Mod.Namespace +
    ".Warnings.Unsupported_Language.Text")  # type: Language.String

GameSTBLPackageMissingNotificationTitle = Language.String(
    This.Mod.Namespace +
    ".Warnings.Game_STBL_Package_Missing.Title")  # type: Language.String
GameSTBLPackageMissingNotificationText = Language.String(
    This.Mod.Namespace +
    ".Warnings.Game_STBL_Package_Missing.Text")  # type: Language.String

GameSTBLPackageReadErrorNotificationTitle = Language.String(
    This.Mod.Namespace +
    ".Warnings.Game_STBL_Package_Read_Error.Title")  # type: Language.String
Beispiel #8
0
from __future__ import annotations

import typing
import webbrowser

from NeonOcean.S4.Main import Debug, Language, Mods, This
from NeonOcean.S4.Main.Tools import Exceptions
from NeonOcean.S4.Main.UI import Dialogs
from sims4 import localization
from ui import ui_dialog

OpenBrowserDialogText = Language.String(This.Mod.Namespace + ".Generic_Dialogs.Open_Browser_Dialog.Text")  # type: Language.String
OpenBrowserDialogYesButton = Language.String(This.Mod.Namespace + ".Generic_Dialogs.Open_Browser_Dialog.Yes_Button", fallbackText = "Yes_Button")  # type: Language.String
OpenBrowserDialogNoButton = Language.String(This.Mod.Namespace + ".Generic_Dialogs.Open_Browser_Dialog.No_Button", fallbackText = "No_Button")  # type: Language.String

AboutModDialogTitle = Language.String(This.Mod.Namespace + ".Generic_Dialogs.About_Mod_Dialog.Title")  # type: Language.String
AboutModDialogText = Language.String(This.Mod.Namespace + ".Generic_Dialogs.About_Mod_Dialog.Text")  # type: Language.String
AboutModDialogOkButton = Language.String(This.Mod.Namespace + ".Generic_Dialogs.About_Mod_Dialog.Ok_Button", fallbackText = "Ok_Button")  # type: Language.String
AboutModDialogUnknown = Language.String(This.Mod.Namespace + ".Generic_Dialogs.About_Mod_Dialog.Unknown", fallbackText = "About_Mod_Dialog.Unknown")  # type: Language.String

def ShowOpenBrowserDialog (url: str, returnCallback: typing.Optional[typing.Callable[[], None]] = None) -> None:
	"""
	Show a dialog asking the user to confirm their intention to open a website in their browser.
	:param url: The url to be opened when the user clicks the ok button.
	:type url: str
	:param returnCallback: Called after the dialog has closed.
	:type returnCallback: typing.Optional[typing.Callable[[], None]]
	"""

	if not isinstance(url, str):
		raise Exceptions.IncorrectTypeException(url, "url", (str,))
Beispiel #9
0
from __future__ import annotations

import interactions
from NeonOcean.S4.Main import Language, Mods, This
from event_testing import results, test_base
from sims4.tuning import tunable

DisabledTooltip = Language.String(
    This.Mod.Namespace + ".Interactions.Support.Dependent.Disabled_Tooltip",
    fallbackText="Disabled_Tooltip")


class DependentTest(test_base.BaseTest):
    # noinspection SpellCheckingInspection
    def __call__(self, affordance):
        if affordance is None:
            return results.TestResult(False)

        if not issubclass(affordance, DependentExtension):
            return results.TestResult(True)

        if affordance.DependentOnMod:
            if affordance.DependentMod is not None:
                if not affordance.DependentMod.IsLoaded():
                    return results.TestResult(
                        False,
                        tooltip=DisabledTooltip.GetCallableLocalizationString(
                            affordance.DependentMod.Namespace))

        return results.TestResult(True)
Beispiel #10
0
from __future__ import annotations

import typing

import zone
from NeonOcean.S4.Main import Director, Language, This
from NeonOcean.S4.Main.Saving import Save, SaveShared
from NeonOcean.S4.Main.UI import Notifications

SavingFirstTimeNotificationTitle = Language.String(
    This.Mod.Namespace +
    ".Saving.Saving_First_Time_Notifications.Title")  # type: Language.String
SavingFirstTimeNotificationText = Language.String(
    This.Mod.Namespace +
    ".Saving.Saving_First_Time_Notifications.Text")  # type: Language.String

_savingObject: SaveShared.Save


class _Announcer(Director.Announcer):
    Host = This.Mod

    @classmethod
    def ZoneLoad(cls, zoneReference: zone.Zone) -> None:
        if not GetSavingObject().LoadedFileExisted:
            _ShowSavingFirstTimeNotification()


def GetSavingObject() -> SaveShared.Save:
    return _savingObject
Beispiel #11
0
class CheckForUpdatesSetting(SettingsBase.Setting):
	Type = dict

	DefaultSetting: typing.Type[SettingsBase.Setting]

	AllModsEnabledText = Language.String(This.Mod.Namespace + ".Settings.Types.Check_For_Updates.All_Mods_Enabled", fallbackText = "Check_For_Updates.All_Mods_Enabled")  # type: Language.String
	NoModsEnabledText = Language.String(This.Mod.Namespace + ".Settings.Types.Check_For_Updates.No_Mods_Enabled", fallbackText = "Check_For_Updates.No_Mods_Enabled")  # type: Language.String
	CustomizedText = Language.String(This.Mod.Namespace + ".Settings.Types.Check_For_Updates.Customized", fallbackText = "Check_For_Updates.Customized")  # type: Language.String

	@classmethod
	def Verify (cls, value: dict, lastChangeVersion: Version.Version = None) -> dict:
		if not isinstance(value, dict):
			raise Exceptions.IncorrectTypeException(value, "value", (dict,))

		if not isinstance(lastChangeVersion, Version.Version) and lastChangeVersion is not None:
			raise Exceptions.IncorrectTypeException(lastChangeVersion, "lastChangeVersion", (Version.Version, "None"))

		for valueKey, valueValue in value.items():  # type: str, bool
			if not isinstance(valueKey, str):
				raise Exceptions.IncorrectTypeException(valueKey, "value<Key>", (str,))

			if not isinstance(valueValue, bool):
				raise Exceptions.IncorrectTypeException(valueValue, "value[%s]" % valueKey, (str,))

		return value

	@classmethod
	def GetValueText (cls, value: typing.Any) -> localization.LocalizedString:
		if not isinstance(value, dict):
			raise Exceptions.IncorrectTypeException(value, "value", (dict,))

		for valueKey, valueValue in value.items():  # type: str, bool
			if not isinstance(valueKey, str):
				raise Exceptions.IncorrectTypeException(valueKey, "value<Key>", (str,))

			if not isinstance(valueValue, bool):
				raise Exceptions.IncorrectTypeException(valueValue, "value[%s]" % valueKey, (str,))

		value = cls.Get()  # type: dict
		defaultSettingValue = cls.DefaultSetting.Get()  # type: bool

		if len(value) == 0:
			if defaultSettingValue:
				return cls.AllModsEnabledText.GetLocalizationString()
			else:
				return cls.NoModsEnabledText.GetLocalizationString()

		allModsEnabled = True  # type: bool
		noModsEnabled = True  # type: bool

		for settingValue in value.values():  # type: str
			if settingValue is False:
				allModsEnabled = False
			elif settingValue is True:
				noModsEnabled = False

		if allModsEnabled and noModsEnabled:
			noModsEnabled = False

		if allModsEnabled:
			return cls.AllModsEnabledText.GetLocalizationString()
		elif noModsEnabled:
			return cls.NoModsEnabledText.GetLocalizationString()
		else:
			return cls.CustomizedText.GetLocalizationString()

	@classmethod
	def _OnLoad (cls) -> None:
		currentValue = cls.Get()  # type: typing.Dict[str, bool]
		defaultValue = cls.DefaultSetting.Get()  # type: bool

		currentValueChanged = False  # type: bool

		for mod in Mods.GetAllMods():  # type: Mods.Mod
			if mod.Distribution.UpdatesController is None:
				continue

			if mod.Namespace not in currentValue:
				currentValue[mod.Namespace] = defaultValue
				currentValueChanged = True

		if currentValueChanged:
			cls.Set(currentValue)
Beispiel #12
0
import indexed_manager
import services
import game_services
import typing
import random
import zone
from NeonOcean.S4.Cycle import Settings, This, Guides as CycleGuides, GuideGroups as CycleGuideGroups, Reproduction, ReproductionShared
from NeonOcean.S4.Cycle.Females import Shared as FemalesShared
from NeonOcean.S4.Cycle.Settings import Base as ModSettingsBase
from NeonOcean.S4.Cycle.SimSettings import Types as SettingsTypes
from NeonOcean.S4.Main import Debug, Director, Language
from NeonOcean.S4.Main.Tools import Events, Exceptions
from sims import sim_info, sim_info_manager, sim_info_types

_AllSimsExperiencePMSOverrideIdentifier = "AllSimsExperiencePMS"  # type: str
_AllSimsExperiencePMSOverrideReason = Language.String(This.Mod.Namespace + ".Sim_Settings.Values.Experiences_PMS.All_Sims_Experience_PMS_Override_Reason", fallbackText = "All_Sims_Experience_PMS_Override_Reason")

_experiencesPMSRollSeed = 519490138  # type: int

class ExperiencesPMS(SettingsTypes.BooleanYesNoDialogSetting):
	IsSetting = True  # type: bool

	Key = "Experiences_PMS"  # type: str
	Default = True  # type: dict

	ListPath = "Root/Menstruation"  # type: str

	@classmethod
	def IsHidden(cls, simID: str) -> bool:
		"""
		Get whether or not this setting should be visible to the user.
Beispiel #13
0
from __future__ import annotations

import os
import pathlib
import typing

import services
from NeonOcean.S4.Main import Debug, Language, Paths, This
from NeonOcean.S4.Main.Saving import Save
from NeonOcean.S4.Main.UI import Dialogs
from ui import ui_dialog, ui_dialog_picker

SelectSaveDialogTitle = Language.String(This.Mod.Namespace + ".Saving.Select_Save_Dialog.Title")  # type: Language.String
SelectSaveDialogText = Language.String(This.Mod.Namespace + ".Saving.Select_Save_Dialog.Text")  # type: Language.String
SelectSaveDialogDescriptionCurrentlyLoaded = Language.String(This.Mod.Namespace + ".Saving.Select_Save_Dialog.Description_Currently_Loaded", fallbackText = "Description_Currently_Loaded")  # type: Language.String
SelectSaveDialogDescriptionNormal = Language.String(This.Mod.Namespace + ".Saving.Select_Save_Dialog.Description_Normal", fallbackText = "Description_Normal")  # type: Language.String

SelectSaveDialogDescriptionMatchMatches = Language.String(This.Mod.Namespace + ".Saving.Select_Save_Dialog.Description_Match.Matches", fallbackText = "Description_Match.Matches")  # type: Language.String
SelectSaveDialogDescriptionMatchMismatchGUID = Language.String(This.Mod.Namespace + ".Saving.Select_Save_Dialog.Description_Match.Mismatch_GUID", fallbackText = "Description_Match.Mismatch_GUID")  # type: Language.String
SelectSaveDialogDescriptionMatchMismatchGameTick = Language.String(This.Mod.Namespace + ".Saving.Select_Save_Dialog.Description_Match.Mismatch_Game_Tick", fallbackText = "Description_Match.Mismatch_Game_Tick")  # type: Language.String
SelectSaveDialogDescriptionMatchUnknown = Language.String(This.Mod.Namespace + ".Saving.Select_Save_Dialog.Description_Match.Unknown", fallbackText = "Description_Match.Unknown")  # type: Language.String

def ShowSelectSaveDialog () -> None:
	gameSaveSlotID = str(services.get_persistence_service().get_save_slot_proto_buff().slot_id)  # type: str
	gameSaveGUID = str(services.get_persistence_service().get_save_slot_proto_guid())  # type: str

	dialogArguments = {
		"owner": services.get_active_sim().sim_info,
		"title": SelectSaveDialogTitle,
		"text": SelectSaveDialogText.GetCallableLocalizationString(*(gameSaveSlotID, gameSaveGUID))
	}
Beispiel #14
0
class Logger:
	WriteFailureNotificationTitle = Language.String(This.Mod.Namespace + ".Write_Failure_Notification.Title")
	WriteFailureNotificationText = Language.String(This.Mod.Namespace + ".Write_Failure_Notification.Text")

	_globalSessionID = "SessionID"  # type: str
	_globalSessionStartTime = "SessionStartTime"  # type: str

	_globalShownWriteFailureNotification = "ShownWriteFailureNotification"  # type: str

	def __init__ (self, loggingRootPath: str, hostNamespace: str = This.Mod.Namespace):
		"""
		An object for logging debug information.
		Logs will be written to a folder named either by the global NeonOcean debugging start time, or the time ChangeLogFile() was last called for this object.

		:param loggingRootPath: The root path all reports sent to this logger object will be written.
		:type loggingRootPath: str
		:param hostNamespace: Errors made by this logger object will show up under this namespace.
		:type hostNamespace: str
		"""

		if not isinstance(loggingRootPath, str):
			raise Exceptions.IncorrectTypeException(loggingRootPath, "loggingRootPath", (str,))

		if not isinstance(hostNamespace, str):
			raise Exceptions.IncorrectTypeException(hostNamespace, "hostNamespace", (str,))

		self.DebugGlobal = Global.GetModule("Debug")

		if not hasattr(self.DebugGlobal, self._globalSessionID) or not isinstance(getattr(self.DebugGlobal, self._globalSessionID), uuid.UUID):
			setattr(self.DebugGlobal, self._globalSessionID, uuid.uuid4())

		if not hasattr(self.DebugGlobal, self._globalSessionStartTime) or not isinstance(getattr(self.DebugGlobal, self._globalSessionStartTime), datetime.datetime):
			setattr(self.DebugGlobal, self._globalSessionStartTime, datetime.datetime.now())

		if not hasattr(self.DebugGlobal, self._globalShownWriteFailureNotification):
			setattr(self.DebugGlobal, self._globalShownWriteFailureNotification, False)

		self.HostNamespace = hostNamespace  # type: str

		self._reportStorage = list()  # type: typing.List[Report]
		self._flushThread = None  # type: typing.Optional[threading.Thread]

		self._loggingRootPath = loggingRootPath  # type: str
		self._loggingDirectoryName = GetDateTimePathString(getattr(self.DebugGlobal, self._globalSessionStartTime))  # type: str

		self._writeFailureCount = 0  # type: int
		self._writeFailureLimit = 2  # type: int
		self._isContinuation = False  # type: bool

		self._sessionInformation = self._CreateSessionInformation()  # type: str
		self._modsDirectoryInformation = self._CreateModsDirectoryInformation()  # type: str

	def Log (self, *args, **kwargs) -> None:
		raise NotImplementedError()

	def GetLoggingRootPath (self) -> str:
		return self._loggingRootPath

	def GetLoggingDirectoryName (self) -> str:
		return self._loggingDirectoryName

	def IsContinuation (self) -> bool:
		return self._isContinuation

	def GetSessionID (self) -> uuid.UUID:
		return getattr(self.DebugGlobal, self._globalSessionID)

	def GetSessionStartTime (self) -> datetime.datetime:
		return getattr(self.DebugGlobal, self._globalSessionStartTime)

	def GetLogStartBytes (self) -> bytes:
		logStartString = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + os.linesep + \
						 "<LogFile SessionID=\"%s\" SessionStartTime=\"%s\">" % (str(self.GetSessionID()), self.GetSessionStartTime().isoformat()) + os.linesep

		return logStartString.encode("utf-8")  # type: bytes

	def GetLogEndBytes (self) -> bytes:
		return (os.linesep + "</LogFile>").encode("utf-8")  # type: bytes

	def ChangeLogFile (self) -> None:
		"""
		Change the current directory name for a new one. The new directory name will be the time this method was called.
		:rtype: None
		"""

		self._loggingDirectoryName = GetDateTimePathString(datetime.datetime.now())
		self._isContinuation = True

		self._sessionInformation = self._CreateSessionInformation()
		self._modsDirectoryInformation = self._CreateModsDirectoryInformation()

	def Flush (self) -> None:
		mainThread = threading.main_thread()  # type: threading.Thread
		mainThreadAlive = mainThread.is_alive()  # type: bool

		currentThreadIsMain = mainThread == threading.current_thread()  # type: bool

		if not mainThreadAlive and not currentThreadIsMain:
			# Unfortunately any daemonic thread's reports will not be written unless they are logged before the last reports from the main thread are written.
			# At this point, any flush thread started will not finish in time before it all comes to an end. Though the flush thread is not daemonic, Python will
			# not stop for it while a shutdown is already in progress. The best way of getting any more reports out during this time would be to co-opt the
			# main thread and make it wait while we write the stored reports.
			return

		if self._flushThread is not None:
			if not mainThreadAlive:
				if self._flushThread.is_alive():
					self._flushThread.join(1)

					if self._flushThread.is_alive():
						return
				else:
					self._flushThread = None
			else:
				return

		if not mainThreadAlive:
			flushThread = self._CreateFlushThread()  # type: threading.Thread
			self._SetFlushThreadUnsafe(flushThread)

			flushThread.start()
			flushThread.join(1)
		else:
			flushThread = self._CreateFlushThread()  # type: threading.Thread

			try:
				self._SetFlushThread(flushThread)
			except ToolsThreading.SimultaneousCallException:
				return

			mainThreadStateChanged = not mainThread.is_alive()  # type: bool

			if mainThreadStateChanged:
				self.Flush()
				return

			flushThread.start()

	def _CreateFlushThread (self) -> threading.Thread:
		mainThread = threading.main_thread()  # type: threading.Thread
		mainThreadAlive = mainThread.is_alive()  # type: bool

		def _FlushThread () -> None:
			nonlocal mainThreadAlive

			mainThreadAlive = mainThread.is_alive()

			try:
				while len(self._reportStorage) != 0:
					reportStorageLength = len(self._reportStorage)  # type: int
					targetReports = self._reportStorage[:reportStorageLength]
					self._reportStorage = self._reportStorage[reportStorageLength:]

					filteredReports = self._FilterReports(targetReports)

					self._LogAllReports(filteredReports)

					mainThreadAlive = mainThread.is_alive()

					if not mainThreadAlive:
						break
			finally:
				self._flushThread = None

			if mainThreadAlive:
				if len(self._reportStorage) != 0:
					self.Flush()

		return threading.Thread(target = _FlushThread, daemon = False)

	@ToolsThreading.NotThreadSafe(raiseException = True)
	def _SetFlushThread (self, flushThread: threading.Thread) -> None:
		self._SetFlushThreadUnsafe(flushThread)

	def _SetFlushThreadUnsafe (self, flushThread: threading.Thread) -> None:
		self._flushThread = flushThread

	def _FilterReports (self, reports: typing.List[Report]) -> typing.List[Report]:
		return list(reports)

	def _LogAllReports (self, reports: typing.List[Report]) -> None:
		raise NotImplementedError()

	def _CreateSessionInformation (self) -> str:
		try:
			installedPacks = list()  # type: typing.List[str]

			for packTuple in common.Pack.items():  # type: typing.Tuple[str, common.Pack]
				if packTuple[1] == common.Pack.BASE_GAME:
					continue

				packAvailable = common.is_available_pack(packTuple[1])

				if packAvailable:
					prefixExpansionPairs = {
						"EP": "Expansion Pack ",
						"GP": "Game Pack ",
						"SP": "Stuff Pack "
					}  # type: typing.Dict[str, str]

					packText = packTuple[0]  # type: str

					for prefix, prefixExpansion in prefixExpansionPairs.items():  # type: str
						if packText.startswith(prefix):
							packText = packText.replace(prefix, prefixExpansion, 1)
							break

					installedPacks.append(packText)

			sessionDictionary = {
				"SessionID": str(self.GetSessionID()),
				"SessionStartTime": self.GetSessionStartTime().isoformat(),
				"IsContinuation": self.IsContinuation(),
				"OS": platform.system(),
				"OSVersion": platform.version(),
				"InstalledPacks": installedPacks
			}

			return json.JSONEncoder(indent = "\t").encode(sessionDictionary)
		except Exception as e:
			return "Failed to get session information\n" + FormatException(e)

	def _CreateModsDirectoryInformation (self) -> str:
		try:
			modFolderString = os.path.split(Paths.ModsPath)[1] + " {" + os.path.split(Paths.ModsPath)[1] + "}"  # type: str

			for directoryRoot, directoryNames, fileNames in os.walk(Paths.ModsPath):  # type: str, list, list
				depth = 1

				if directoryRoot != Paths.ModsPath:
					depth = len(directoryRoot.replace(Paths.ModsPath + os.path.sep, "").split(os.path.sep)) + 1  # type: int

				indention = "\t" * depth  # type: str

				newString = ""  # type: str

				for directory in directoryNames:
					newString += "\n" + indention + directory + " {" + directory + "}"

				for file in fileNames:
					newString += "\n" + indention + file + " (" + str(os.path.getsize(os.path.join(directoryRoot, file))) + " B)"

				if len(newString) == 0:
					newString = "\n"

				newString += "\n"

				modFolderString = modFolderString.replace("{" + os.path.split(directoryRoot)[1] + "}", "{" + newString + "\t" * (depth - 1) + "}", 1)

			return modFolderString
		except Exception as e:
			return "Failed to get mod information\n" + FormatException(e)

	def _VerifyLogFile (self, logFilePath: str) -> None:
		logEndBytes = self.GetLogEndBytes()  # type: bytes

		with open(logFilePath, "rb") as logFile:
			logFile.seek(-len(logEndBytes), os.SEEK_END)

			if logEndBytes != logFile.read():
				raise Exception("The end of the log file doesn't match what was expected.")

	def _ShowWriteFailureDialog (self, exception: Exception) -> None:
		Notifications.ShowNotification(queue = True,
									   title = self.WriteFailureNotificationTitle.GetCallableLocalizationString(),
									   text = self.WriteFailureNotificationText.GetCallableLocalizationString(FormatException(exception)),
									   expand_behavior = ui_dialog_notification.UiDialogNotification.UiDialogNotificationExpandBehavior.FORCE_EXPAND,
									   urgency = ui_dialog_notification.UiDialogNotification.UiDialogNotificationUrgency.URGENT)
Beispiel #15
0
from NeonOcean.S4.Main import Debug, Language, LoadingShared
from NeonOcean.S4.Main.UI import Dialogs
from server_commands import argument_helpers
from sims import sim_info
from sims4 import collections
from ui import ui_dialog, ui_dialog_generic, ui_text_input

ShowReproductiveInfoCommand: Command.ConsoleCommand
ShowSetCycleProgressDialogCommand: Command.ConsoleCommand
MakePregnantCommand: Command.ConsoleCommand
EndPregnancyCommand: Command.ConsoleCommand
ShowSetPregnancyProgressDialogCommand: Command.ConsoleCommand
FixDotCycleCommand: Command.ConsoleCommand

SetCycleProgressDialogText = Language.String(
    This.Mod.Namespace +
    ".Set_Cycle_Progress_Dialog.Text")  # type: Language.String
SetCycleProgressDialogTitle = Language.String(
    This.Mod.Namespace +
    ".Set_Cycle_Progress_Dialog.Title")  # type: Language.String
SetCycleProgressDialogOkButton = Language.String(
    This.Mod.Namespace + ".Set_Cycle_Progress_Dialog.Ok_Button",
    fallbackText="Ok_Button")  # type: Language.String
SetCycleProgressDialogCancelButton = Language.String(
    This.Mod.Namespace + ".Set_Cycle_Progress_Dialog.Cancel_Button",
    fallbackText="Cancel_Button")  # type: Language.String

SetPregnancyProgressDialogText = Language.String(
    This.Mod.Namespace +
    ".Set_Pregnancy_Progress_Dialog.Text")  # type: Language.String
SetPregnancyProgressDialogTitle = Language.String(
Beispiel #16
0
from NeonOcean.S4.Cycle import This
from NeonOcean.S4.Main import Language
from NeonOcean.S4.Main.Tools import Exceptions
from NeonOcean.S4.Main.UI import Notifications
from distributor import shared_messages
from sims import sim_info
from ui import ui_dialog_notification

MissedPillNotificationTitle = Language.String(
    This.Mod.Namespace + ".Birth_Control_Pills.Missed_Pill_Notification.Title"
)  # type: Language.String
MissedPillNotificationText = Language.String(
    This.Mod.Namespace + ".Birth_Control_Pills.Missed_Pill_Notification.Text"
)  # type: Language.String


def ShowMissedPillNotification(targetSimInfo: sim_info.SimInfo,
                               missedPills: int) -> None:
    """
	Show a notification indicating that the target sim forgot to take this many pills.
	"""

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

    if not isinstance(missedPills, int):
        raise Exceptions.IncorrectTypeException(missedPills, "missedPills",
                                                (int, ))

    notificationArguments = {
Beispiel #17
0
class _Logger(DebugShared.Logger):
    WriteFailureNotificationTitle = Language.String(
        This.Mod.Namespace + ".Write_Failure_Notification.Title")
    WriteFailureNotificationText = Language.String(
        This.Mod.Namespace + ".Write_Failure_Notification.Text")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.LogCount = 0

    def Log(self,
            message,
            level: Debug.LogLevels,
            group: str = None,
            owner: str = None,
            logStack: bool = False,
            exception: BaseException = None,
            frame: types.FrameType = None) -> None:

        if not isinstance(level, int):
            raise Exceptions.IncorrectTypeException(level, "level", (int, ))

        if not isinstance(group, str) and group is not None:
            raise Exceptions.IncorrectTypeException(group, "group", (str, ))

        if not isinstance(owner, str) and owner is not None:
            raise Exceptions.IncorrectTypeException(owner, "owner", (str, ))

        if not isinstance(exception, BaseException) and exception is not None:
            raise Exceptions.IncorrectTypeException(exception, "exception",
                                                    (BaseException, ))

        if not isinstance(logStack, bool):
            raise Exceptions.IncorrectTypeException(logStack, "logStack",
                                                    (bool, ))

        if isinstance(frame, singletons.DefaultType):
            frame = None

        if not isinstance(frame, types.FrameType) and frame is not None:
            raise Exceptions.IncorrectTypeException(frame, "frame",
                                                    (types.FrameType, ))

        if self._writeFailureCount >= self._writeFailureLimit:
            return

        if not _loggingEnabled and _loggingEnabled is not None:
            return

        if frame is log.DEFAULT:
            frame = None

        if exception is None:
            exception = sys.exc_info()[1]

        logCount = self.LogCount  # type: int
        self.LogCount += 1

        if _logLevel is not None:
            if level > _logLevel:
                return

        report = DebugShared.Report(
            None,
            logCount + 1,
            datetime.datetime.now().isoformat(),
            str(message),
            level=level,
            group=str(group),
            owner=owner,
            exception=exception,
            logStack=logStack,
            stacktrace=str.join(
                "",
                traceback.format_stack(f=frame)))  # type: DebugShared.Report

        self._reportStorage.append(report)

        if _logInterval == 0:
            self.Flush()

    def GetLogSizeLimit(self) -> int:
        return int(_logSizeLimit * 1000000)

    def GetLogFilesToBeReported(self) -> typing.List[str]:
        """
		Get the logs to be included in a report archive file. This should be limited to only some of the more recent logs.
		"""

        reportingLogFiles = list()  # type: typing.List[str]

        loggingRootPath = self.GetLoggingRootPath()  # type: str

        reportingLogDirectories = list()  # type: typing.List[str]

        latestLogFilePath = os.path.join(loggingRootPath,
                                         "Latest.xml")  # type: str

        if os.path.exists(latestLogFilePath):
            reportingLogFiles.append(latestLogFilePath)

        for logDirectoryName in reversed(
                os.listdir(loggingRootPath)):  # type: str
            if len(reportingLogDirectories) >= 10:
                break

            logDirectoryPath = os.path.join(loggingRootPath,
                                            logDirectoryName)  # type: str

            if not os.path.isdir(logDirectoryPath):
                continue

            try:
                datetime.datetime.strptime(
                    logDirectoryName,
                    "%Y-%m-%d %H.%M.%S.%f").timestamp()  # type: float
            except ValueError:
                Debug.Log(
                    "Found a directory in a logging namespace that did not meet the naming convention of 'Year-Month-Day Hour.Minute.Second.Microsecond'.\nDirectory Name: %s"
                    % logDirectoryName,
                    This.Mod.Namespace,
                    Debug.LogLevels.Warning,
                    group=This.Mod.Namespace,
                    owner=__name__,
                    lockIdentifier=__name__ + ":" +
                    str(Python.GetLineNumber()),
                    lockThreshold=1)
                continue

            reportingLogDirectories.append(logDirectoryPath)

        for reportingLogDirectory in reportingLogDirectories:  # type: str
            reportingLogFilePath = os.path.join(reportingLogDirectory,
                                                "Log.xml")  # type: str

            if os.path.exists(reportingLogFilePath):
                reportingLogFiles.append(reportingLogFilePath)

            reportingSessionFilePath = os.path.join(
                reportingLogDirectory, "Session.json")  # type: str

            if os.path.exists(reportingSessionFilePath):
                reportingLogFiles.append(reportingSessionFilePath)

            reportingModFilePath = os.path.join(reportingLogDirectory,
                                                "Mods.txt")  # type: str

            if os.path.exists(reportingModFilePath):
                reportingLogFiles.append(reportingModFilePath)

        return reportingLogFiles

    def _FilterReports(
        self, reports: typing.List[DebugShared.Report]
    ) -> typing.List[DebugShared.Report]:
        def Filter(report: DebugShared.Report) -> bool:
            if _logLevel is not None:
                if report.Level > _logLevel:
                    return False

            return True

        return list(filter(Filter, reports))

    def _LogAllReports(self, reports: typing.List[DebugShared.Report]) -> None:
        if not _writeChronological and not _writeGroups:
            return

        if len(reports) == 0:
            return

        chronologicalTextBytes = bytes()  # type: bytes
        groupsTextBytes = dict()  # type: typing.Dict[str, bytes]

        writeTime = datetime.datetime.now().isoformat()  # type: str

        for report in reports:  # type: DebugShared.Report
            group = str(report.Group)  # type: str
            reportTextBytes = report.GetBytes(
                writeTime=writeTime)  # type: bytes

            if _writeChronological:
                if len(chronologicalTextBytes) != 0:
                    chronologicalTextBytes += (os.linesep + os.linesep).encode(
                        "utf-8") + reportTextBytes
                else:
                    chronologicalTextBytes = reportTextBytes

            if _writeGroups:
                if group in groupsTextBytes:
                    groupsTextBytes[group] += (os.linesep + os.linesep).encode(
                        "utf-8") + reportTextBytes
                else:
                    groupsTextBytes[group] = reportTextBytes

        loggingRoot = self.GetLoggingRootPath()  # type: str

        loggingDirectory = os.path.join(
            loggingRoot, self.GetLoggingDirectoryName())  # type: str
        chronologicalFilePath = os.path.join(loggingDirectory,
                                             "Log.xml")  # type: str
        chronologicalFirstWrite = False  # type: bool
        latestChronologicalFilePath = os.path.join(loggingRoot,
                                                   "Latest.xml")  # type: str

        groupsLoggingDirectory = os.path.join(loggingDirectory,
                                              "Groups")  # type: str

        sessionFilePath = os.path.join(loggingDirectory,
                                       "Session.txt")  # type: str
        modsDirectoryFilePath = os.path.join(loggingDirectory,
                                             "Mods Directory.txt")  # type: str

        logSizeLimit = self.GetLogSizeLimit()  # type: int
        logSizeLimitReachedBytes = "<!--Log file size limit reached-->".encode(
            "utf-8")  # type: bytes

        logStartBytes = self.GetLogStartBytes()  # type: bytes
        logEndBytes = self.GetLogEndBytes()  # type: bytes

        lineSeparatorBytes = (os.linesep + os.linesep).encode(
            "utf-8")  # type: bytes

        try:
            if not os.path.exists(loggingDirectory):
                os.makedirs(loggingDirectory)

            if _writeGroups:
                if not os.path.exists(groupsLoggingDirectory):
                    os.makedirs(groupsLoggingDirectory)

            if not os.path.exists(sessionFilePath):
                with open(sessionFilePath, mode="w+") as sessionFile:
                    sessionFile.write(self._sessionInformation)

            if not os.path.exists(modsDirectoryFilePath):
                with open(modsDirectoryFilePath, mode="w+") as modsFile:
                    modsFile.write(self._modsDirectoryInformation)

            if _writeChronological:
                if not os.path.exists(chronologicalFilePath):
                    chronologicalFirstWrite = True
                else:
                    self._VerifyLogFile(chronologicalFilePath)

                if chronologicalFirstWrite:
                    if len(logStartBytes) + len(chronologicalTextBytes) + len(
                            logEndBytes) >= logSizeLimit >= 0:
                        chronologicalTextBytes += logSizeLimitReachedBytes

                    with open(chronologicalFilePath,
                              mode="wb+") as chronologicalFile:
                        chronologicalFile.write(logStartBytes)
                        chronologicalFile.write(chronologicalTextBytes)
                        chronologicalFile.write(logEndBytes)

                    if os.path.exists(latestChronologicalFilePath):
                        os.remove(latestChronologicalFilePath)

                    with open(latestChronologicalFilePath,
                              mode="wb+") as latestChronologicalFile:
                        latestChronologicalFile.write(logStartBytes)
                        latestChronologicalFile.write(chronologicalTextBytes)
                        latestChronologicalFile.write(logEndBytes)
                else:
                    logSize = os.path.getsize(
                        chronologicalFilePath)  # type: int

                    if logSizeLimit < 0 or logSize < logSizeLimit:
                        if logSize + len(lineSeparatorBytes) + len(
                                chronologicalTextBytes) + len(
                                    logEndBytes) >= logSizeLimit >= 0:
                            chronologicalTextBytes += logSizeLimitReachedBytes

                        with open(chronologicalFilePath,
                                  "r+b") as chronologicalFile:
                            chronologicalFile.seek(-len(logEndBytes),
                                                   os.SEEK_END)
                            chronologicalFile.write(lineSeparatorBytes)
                            chronologicalFile.write(chronologicalTextBytes)
                            chronologicalFile.write(logEndBytes)

                        try:
                            self._VerifyLogFile(latestChronologicalFilePath)

                            with open(latestChronologicalFilePath,
                                      "r+b") as latestChronologicalFile:
                                latestChronologicalFile.seek(
                                    -len(logEndBytes), os.SEEK_END)
                                latestChronologicalFile.write(
                                    lineSeparatorBytes)
                                latestChronologicalFile.write(
                                    chronologicalTextBytes)
                                latestChronologicalFile.write(logEndBytes)
                        except:
                            shutil.copy(chronologicalFilePath,
                                        latestChronologicalFilePath)

            for groupName, groupTextBytes in groupsTextBytes.items(
            ):  # type: str, bytes
                groupFilePath = os.path.join(groupsLoggingDirectory,
                                             groupName + ".xml")  # type: str
                groupFirstWrite = False  # type: bool

                if _writeGroups:
                    if not os.path.exists(groupFilePath):
                        groupFirstWrite = True
                    else:
                        self._VerifyLogFile(groupFilePath)

                    if groupFirstWrite:
                        if len(logStartBytes) + len(groupsTextBytes) + len(
                                logEndBytes) >= logSizeLimit >= 0:
                            groupsTextBytes += logSizeLimitReachedBytes

                        with open(groupFilePath, mode="wb+") as groupFile:
                            groupFile.write(logStartBytes)
                            groupFile.write(groupTextBytes)
                            groupFile.write(logEndBytes)
                    else:
                        logSize = os.path.getsize(
                            chronologicalFilePath)  # type: int

                        if logSizeLimit < 0 or logSize < logSizeLimit:
                            if logSize + len(lineSeparatorBytes) + len(
                                    groupsTextBytes) + len(
                                        logEndBytes) >= logSizeLimit >= 0:
                                groupsTextBytes += logSizeLimitReachedBytes

                            with open(groupFilePath, "r+b") as groupFile:
                                groupFile.seek(-len(logEndBytes), os.SEEK_END)
                                groupFile.write((os.linesep +
                                                 os.linesep).encode("utf-8") +
                                                groupTextBytes)
                                groupFile.write(logEndBytes)
        except Exception as e:
            self._writeFailureCount += 1

            if not getattr(self.DebugGlobal,
                           self._globalShownWriteFailureNotification):
                self._ShowWriteFailureDialog(e)
                setattr(self.DebugGlobal,
                        self._globalShownWriteFailureNotification, True)

            if self._writeFailureCount < self._writeFailureLimit:
                self.ChangeLogFile()

                retryingReports = list(
                    filter(lambda filterReport: filterReport.RetryOnError,
                           reports))  # type: typing.List[DebugShared.Report]
                retryingReportsLength = len(retryingReports)  # type: int

                Debug.Log(
                    "Forced to start a new log file after encountering a write error. "
                    + str(len(reports) - retryingReportsLength) +
                    " reports where lost because of this.",
                    This.Mod.Namespace,
                    Debug.LogLevels.Exception,
                    group=This.Mod.Namespace,
                    owner=__name__,
                    retryOnError=False)

                for retryingReport in retryingReports:
                    retryingReport.RetryOnError = False

                if retryingReportsLength != 0:
                    self._LogAllReports(reports)

            return
Beispiel #18
0
import os
import typing

from NeonOcean.S4.Main import Debug, LoadingShared, Reporting, This, Language, Paths
from NeonOcean.S4.Main.UI import Dialogs
from NeonOcean.S4.Main.Console import Command
from sims4 import commands
from ui import ui_dialog

ShowPrepareReportLocationDialogCommand: Command.ConsoleCommand

PrepareReportLocationDialogTitle = Language.String(
    This.Mod.Namespace + ".Reporting.Dialogs.Prepare_Report_Location.Title",
    fallbackText="Prepare_Report_Location.Title")  # type: Language.String
PrepareReportLocationDialogText = Language.String(
    This.Mod.Namespace +
    ".Reporting.Dialogs.Prepare_Report_Location.Text")  # type: Language.String
PrepareReportLocationDialogCancelButton = Language.String(
    This.Mod.Namespace +
    ".Reporting.Dialogs.Prepare_Report_Location.Cancel_Button",
    fallbackText="Cancel_Button")  # type: Language.String
PrepareReportLocationDialogDesktopButton = Language.String(
    This.Mod.Namespace +
    ".Reporting.Dialogs.Prepare_Report_Location.Desktop_Button",
    fallbackText="Desktop_Button")  # type: Language.String
PrepareReportLocationDialogGameUserDataButton = Language.String(
    This.Mod.Namespace +
    ".Reporting.Dialogs.Prepare_Report_Location.Game_User_Data_Button",
    fallbackText="Game_User_Data_Button")  # type: Language.String

ReportCreatedDialogTitle = Language.String(
Beispiel #19
0
import typing

from NeonOcean.S4.Cycle import Reproduction, ReproductionShared, This
from NeonOcean.S4.Cycle.Females import Shared as FemalesShared, PregnancyTracker
from NeonOcean.S4.Main.Tools import Exceptions
from NeonOcean.S4.Main import Language
from NeonOcean.S4.Main.UI import Notifications
from distributor import shared_messages
from sims import sim_info

PositiveTestResultNotificationTitle = Language.String(
    This.Mod.Namespace +
    ".Pregnancy_Test.Positive_Test_Result_Notification.Title"
)  # type: Language.String
PositiveTestResultNotificationText = Language.String(
    This.Mod.Namespace +
    ".Pregnancy_Test.Positive_Test_Result_Notification.Text"
)  # type: Language.String

NegativeTestResultNotificationTitle = Language.String(
    This.Mod.Namespace +
    ".Pregnancy_Test.Negative_Test_Result_Notification.Title"
)  # type: Language.String
NegativeTestResultNotificationText = Language.String(
    This.Mod.Namespace +
    ".Pregnancy_Test.Negative_Test_Result_Notification.Text"
)  # type: Language.String


def ShowTestResultNotification(targetSimInfo: sim_info.SimInfo) -> None:
    if not isinstance(targetSimInfo, sim_info.SimInfo):
Beispiel #20
0
import typing

import clock
import date_and_time
import services
from NeonOcean.S4.Cycle import Dot, This
from NeonOcean.S4.Cycle.Females.Cycle import Shared as CycleShared
from NeonOcean.S4.Cycle.UI import Resources as CycleUIResources
from NeonOcean.S4.Main import Debug, Language
from NeonOcean.S4.Main.Tools import Exceptions, TextBuilder
from NeonOcean.S4.Main.UI import Notifications
from distributor import shared_messages
from sims import sim_info
from sims4 import localization, resources

StatusNotificationTitle = Language.String(This.Mod.Namespace + ".Dot.Status_Notification.Title")  # type: Language.String

StatusNotificationTextTimePeriodStartingToday = Language.String(This.Mod.Namespace + ".Dot.Status_Notification.Text.Time_Period.Starting.Today")  # type: Language.String
StatusNotificationTextTimePeriodStartingTomorrow = Language.String(This.Mod.Namespace + ".Dot.Status_Notification.Text.Time_Period.Starting.Tomorrow")  # type: Language.String
StatusNotificationTextTimePeriodStartingInDays = Language.String(This.Mod.Namespace + ".Dot.Status_Notification.Text.Time_Period.Starting.In_Days")  # type: Language.String
StatusNotificationTextTimePeriodEndingToday = Language.String(This.Mod.Namespace + ".Dot.Status_Notification.Text.Time_Period.Ending.Today")  # type: Language.String
StatusNotificationTextTimePeriodEndingTomorrow = Language.String(This.Mod.Namespace + ".Dot.Status_Notification.Text.Time_Period.Ending.Tomorrow")  # type: Language.String
StatusNotificationTextTimePeriodEndingInDays = Language.String(This.Mod.Namespace + ".Dot.Status_Notification.Text.Time_Period.Ending.In_Days")  # type: Language.String

StatusNotificationTextFollicular = Language.String(This.Mod.Namespace + ".Dot.Status_Notification.Text.Follicular")  # type: Language.String
StatusNotificationTextLuteal = Language.String(This.Mod.Namespace + ".Dot.Status_Notification.Text.Luteal")  # type: Language.String

StatusNotificationTextOvulationStarting = Language.String(This.Mod.Namespace + ".Dot.Status_Notification.Text.Ovulation.Starting")  # type: Language.String
StatusNotificationTextOvulationEnding = Language.String(This.Mod.Namespace + ".Dot.Status_Notification.Text.Ovulation.Ending")  # type: Language.String

StatusNotificationTextMenstruationStarting = Language.String(This.Mod.Namespace + ".Dot.Status_Notification.Text.Menstruation.Starting")  # type: Language.String
Beispiel #21
0
from NeonOcean.S4.Cycle.Safety import BirthControlPills as SafetyBirthControlPills, Resources as SafetyResources
from NeonOcean.S4.Main import Debug, Director, Language
from NeonOcean.S4.Main.Interactions.Support import DisableInteraction
from NeonOcean.S4.Main.Tools import Exceptions, Patcher, Python
from event_testing import results
from objects import script_object
from objects.components import inventory as ComponentsInventory, types as ComponentsTypes
from sims import sim, sim_info
from sims4 import resources
from sims4.tuning import instance_manager
"""
If your the creator of wicked whims - [email protected] - It might be better if you do some of these patches.
"""

DisabledBecauseWickedWhimsInstalledToolTip = Language.String(
    This.Mod.Namespace + ".Mods.WickedWhims.Disabled_Because_Installed_Tooltip"
)  # type: Language.String
DisabledBecauseCycleInstalledToolTip = Language.String(
    This.Mod.Namespace +
    ".Mods.Cycle.Disabled_Because_Installed_Tooltip")  # type: Language.String

WickedWhimsBirthControlPillsObjectID = 11109047836475721558  # type: int
WickedWhimsCheckCyclesInfoInteractionID = 9855519195140041011  # type: int


class _Announcer(Director.Announcer):
    @classmethod
    def InstanceManagerOnStart(
            cls, instanceManager: instance_manager.InstanceManager) -> None:
        if instanceManager.TYPE != resources.Types.INTERACTION:
            return
Beispiel #22
0
from __future__ import annotations

import inspect
import sys
import types
import typing

from NeonOcean.S4.Main import Debug, Language, Mods, This
from NeonOcean.S4.Main.UI import Dialogs
from ui import ui_dialog

DialogTitle = Language.String(This.Mod.Namespace +
                              ".Reset.Dialog.Title")  # type: Language.String
DialogText = Language.String(This.Mod.Namespace +
                             ".Reset.Dialog.Text")  # type: Language.String
DialogEverythingButton = Language.String(
    This.Mod.Namespace + ".Reset.Dialog.Everything_Button",
    fallbackText="Everything_Button")  # type: Language.String
DialogSettingsButton = Language.String(
    This.Mod.Namespace + ".Reset.Dialog.Settings_Button",
    fallbackText="Settings_Button")  # type: Language.String
DialogCancelButton = Language.String(
    This.Mod.Namespace + ".Reset.Dialog.Cancel_Button",
    fallbackText="Cancel_Button")  # type: Language.String

ConfirmDialogTitle = Language.String(
    This.Mod.Namespace +
    ".Reset.Confirm_Dialog.Title")  # type: Language.String
ConfirmDialogEverythingText = Language.String(
    This.Mod.Namespace +
    ".Reset.Confirm_Dialog.Everything_Text")  # type: Language.String
Beispiel #23
0
class EnglishLanguageHandler(LanguageHandlers.LanguageHandlerBase):
    IsLanguageHandler = True  # type: bool

    HandlingLanguage = LanguageHandlers.Language.English  # type: LanguageHandlers.Language

    GameIdentifier = "en-us"  # type: str

    TheyThemSetIdentifier = "4CAA6EA8-3D59-4F6B-8842-ABB7F5A5AC27"  # type: str
    TheyThemSetTitle = "They / Them"  # type: str

    ZeZirSetIdentifier = "A5149C53-6B7E-4E26-AA6E-A38DD8AC8743"  # type: str
    ZeZirTitle = "Ze / Zir"

    ZeHirSetIdentifier = "FB11090A-EC13-4437-832C-B0E0C78B89F9"  # type: str
    ZeHirTitle = "Ze / Hir"

    XeXemSetIdentifier = "055ECB20-EFD0-477A-91EC-927C947F7E60"  # type: str
    XeXemTitle = "Xe / Xem"

    EyEmSetIdentifier = "34B839A1-0ADC-42A8-A2E7-6161D6804945"  # type: str
    EyEmTitle = "Ey / Em"

    ItSetIdentifier = "2C7EC16C-D1BB-496A-987A-D3D95981FB48"  # type: str
    ItTitle = "It"

    STBLInstanceIDPrefix = "00"  # type: str

    GameLocalizationPackageFileName = "Strings_ENG_US.package"  # type: str

    AskToDoTheyAreFixDialogTitle = Language.String(
        This.Mod.Namespace +
        ".Language_Handlers.English.Ask_To_Do_They_Are_Fix_Dialog.Title",
        fallbackText="Ask_To_Do_They_Are_Fix_Dialog.Title")
    AskToDoTheyAreFixDialogText = Language.String(
        This.Mod.Namespace +
        ".Language_Handlers.English.Ask_To_Do_They_Are_Fix_Dialog.Text",
        fallbackText="Ask_To_Do_They_Are_Fix_Dialog.Text")
    AskToDoTheyAreFixDialogYesButton = Language.String(
        This.Mod.Namespace +
        ".Language_Handlers.English.Ask_To_Do_They_Are_Fix_Dialog.Yes_Button",
        fallbackText="Ask_To_Do_They_Are_Fix_Dialog.Yes_Button")
    AskToDoTheyAreFixDialogNoButton = Language.String(
        This.Mod.Namespace +
        ".Language_Handlers.English.Ask_To_Do_They_Are_Fix_Dialog.No_Button",
        fallbackText="Ask_To_Do_They_Are_Fix_Dialog.No_Button")

    @classmethod
    def GetHandlerVersion(cls) -> Version.Version:
        return This.Mod.Version

    @classmethod
    def GetMinimumCacheHandlerVersion(cls) -> typing.Optional[Version.Version]:
        return None

    @classmethod
    def GetGenderTagTextIdentifierPart(cls, tagText: str) -> str:
        if not isinstance(tagText, str):
            raise Exceptions.IncorrectTypeException(tagText, "tagText",
                                                    (str, ))

        standardizeTagText = tagText.lower().strip(" ")  # type: str

        return {
            "she's": "she’s",  # Standardize apostrophe characters.
            "he's": "he’s",
            "she'll": "she’ll",
            "he'll": "he’ll",
            "she'd": "she’d",
            "he'd": "he’d",
            "mr":
            "mr.",  # Standardize mr and ms. Some of game's mr and ms tags don't have trailing dots, while others do. This handles that inconsistency.
            "ms": "ms."
        }.get(standardizeTagText, standardizeTagText)

    @classmethod
    def FixGenderTagUsageInconsistency(
        cls, text: str, cachedGenderTagPairMatches: typing.List[
            GenderedLanguage.CachedGenderTagPairMatch]
    ) -> str:
        fixedText = ""  # type: str

        unfixedTextStartPosition = None  # type: typing.Optional[int]

        girlBoyTagTexts = {"girl", "boy"}  # type: typing.Set[str]

        for cachedPairMatch in cachedGenderTagPairMatches:  # type: GenderedLanguage.CachedGenderTagPairMatch
            nextUnfixedTextStartPosition = cachedPairMatch.MatchEndPosition  # type: int

            if cachedPairMatch.FirstTagTextLower in girlBoyTagTexts and cachedPairMatch.SecondTagTextLower in girlBoyTagTexts:
                textAfterGenderTag = text[
                    cachedPairMatch.MatchEndPosition:
                    cachedPairMatch.MatchEndPosition +
                    6]  # type: str  # 6 is the number of characters in 'friend'.

                if textAfterGenderTag.lower() == "friend":
                    fixedText += text[unfixedTextStartPosition: cachedPairMatch.MatchStartPosition] + \
                        ("{%s%s.%s%s}{%s%s.%s%s}" % (
                         cachedPairMatch.FirstTagGender, cachedPairMatch.FirstTagTokenIndexString, cachedPairMatch.FirstTagText, textAfterGenderTag,
                         cachedPairMatch.SecondTagGender, cachedPairMatch.SecondTagTokenIndexString, cachedPairMatch.SecondTagText, textAfterGenderTag
                        ))

                    unfixedTextStartPosition = nextUnfixedTextStartPosition + 6
                    continue

            fixedText += text[unfixedTextStartPosition:cachedPairMatch.
                              MatchEndPosition]
            unfixedTextStartPosition = nextUnfixedTextStartPosition
            continue

        fixedText += text[unfixedTextStartPosition:]

        return fixedText

    @classmethod
    def GetStandardPronounSets(cls) -> dict:
        standardSets = dict()  # type: dict
        standardSets.update(cls._CreateTheyThemSet())
        standardSets.update(cls._CreateZeZirSet())
        standardSets.update(cls._CreateZeHirSet())
        standardSets.update(cls._CreateXeXemSet())
        standardSets.update(cls._CreateEyEmSet())
        standardSets.update(cls._CreateItSet())
        return standardSets

    @classmethod
    def GetReservedPronounSetIdentifiers(cls) -> list:
        return [
            cls.TheyThemSetIdentifier, cls.ZeZirSetIdentifier,
            cls.ZeHirSetIdentifier, cls.XeXemSetIdentifier,
            cls.EyEmSetIdentifier, cls.ItSetIdentifier
        ]

    @classmethod
    def IsHandlingLanguageSTBLFile(cls, stblInstanceHexID: str) -> bool:
        if not isinstance(stblInstanceHexID, str):
            raise Exceptions.IncorrectTypeException(stblInstanceHexID,
                                                    "stblInstanceHexID",
                                                    (str, ))

        return stblInstanceHexID.startswith(cls.STBLInstanceIDPrefix)

    @classmethod
    def GetPackLocalizationPackageFilePaths(
            cls, pack: Sims4Common.Pack) -> typing.List[str]:
        if not isinstance(pack, Sims4Common.Pack):
            raise Exceptions.IncorrectTypeException(pack, "pack",
                                                    (Sims4Common.Pack, ))

        if game_services.service_manager is None or game_services.service_manager.client_manager is None:
            return list()

        if pack in LanguageHandlers.NoLocalizationPackagePacks:
            return list()

        if sys.platform.lower() == "darwin":  # The game is running on a MAC pc

            # Note: In these notes "..." only means there is more to the path.
            # This is something that is done to this path in the paths module..
            appAndPacksRootPath = os.path.dirname(
                os.path.
                dirname(  # ".../Applications/The Sims 4.app/Contents" > ".../Applications"
                    os.path.normpath(
                        os.path.abspath(paths.APP_ROOT)
                    )  # ".../Applications/The Sims 4.app/Contents/" > ".../Applications/The Sims 4.app/Contents
                ))  # type: str

            gameAppContentsPath = os.path.normpath(
                os.path.abspath(paths.APP_ROOT))  # type: str

            if pack == Sims4Common.Pack.BASE_GAME:
                baseGameLocalizationPackageFilePath = os.path.join(
                    gameAppContentsPath, "Data", "Client",
                    cls.GameLocalizationPackageFileName)  # type: str

                if not os.path.exists(baseGameLocalizationPackageFilePath):
                    Debug.Log(
                        "Could not find the base game's localization package file.\nExpected Location: %s"
                        % baseGameLocalizationPackageFilePath,
                        This.Mod.Namespace,
                        Debug.LogLevels.Warning,
                        group=This.Mod.Namespace,
                        owner=__name__)
                    return list()

                return [baseGameLocalizationPackageFilePath]

            else:
                packLocalizationPackageFilePath = os.path.join(
                    appAndPacksRootPath, "The Sims 4 Packs", pack.name.upper(),
                    cls.GameLocalizationPackageFileName)  # type: str

                if not os.path.exists(packLocalizationPackageFilePath):
                    Debug.Log(
                        "Could not find a pack's localization package file.\nPack: %s\nExpected Location: %s"
                        % (pack.name, packLocalizationPackageFilePath),
                        This.Mod.Namespace,
                        Debug.LogLevels.Warning,
                        group=This.Mod.Namespace,
                        owner=__name__)
                    return list()

                return [packLocalizationPackageFilePath]

        else:
            # Assume its running on Windows otherwise.

            # Note: In these notes "..." only means there is more to the path.
            # This is something that is done to this path in the paths module.
            gameRootPath = os.path.dirname(
                os.path.
                dirname(  # "...\The Sims 4\Game\Bin" > "...\The Sims 4"
                    os.path.normpath(
                        os.path.abspath(paths.APP_ROOT)
                    )  # "...\The Sims 4\Game\Bin\" > "...\The Sims 4\Game\Bin"
                ))  # type: str

            if pack == Sims4Common.Pack.BASE_GAME:
                baseGameLocalizationPackageFilePath = os.path.join(
                    gameRootPath, "Data", "Client",
                    cls.GameLocalizationPackageFileName)  # type: str

                if not os.path.exists(baseGameLocalizationPackageFilePath):
                    Debug.Log(
                        "Could not find the base game's localization package file.\nExpected Location: %s"
                        % baseGameLocalizationPackageFilePath,
                        This.Mod.Namespace,
                        Debug.LogLevels.Warning,
                        group=This.Mod.Namespace,
                        owner=__name__)
                    return list()

                return [baseGameLocalizationPackageFilePath]

            else:
                packLocalizationPackageFilePath = os.path.join(
                    gameRootPath, pack.name.upper(),
                    cls.GameLocalizationPackageFileName)  # type: str

                if not os.path.exists(packLocalizationPackageFilePath):
                    Debug.Log(
                        "Could not find a pack's localization package file.\nPack: %s\nExpected Location: %s"
                        % (pack.name, packLocalizationPackageFilePath),
                        This.Mod.Namespace,
                        Debug.LogLevels.Warning,
                        group=This.Mod.Namespace,
                        owner=__name__)
                    return list()

                return [packLocalizationPackageFilePath]

    @classmethod
    def GetCustomPronounSetEditableGenderTagPairs(cls) -> typing.List[str]:
        """
		Get a list of gender tag pairs that are editable when creating a custom pronoun set.
		"""

        return [
            "she|he", "her|him", "her|his", "hers|his", "she’s|he’s",
            "she’ll|he’ll", "she’d|he’d", "herself|himself"
        ]

    @classmethod
    def GetCustomPronounSetStandardValues(cls) -> typing.Dict[str, str]:
        """
		Get the standard values that custom pronoun sets should have.
		"""

        return {
            "ms.|mr.": "mx.",
            "girlfriend|boyfriend": "partner",
            "sister|brother": "sibling",
            "mother|father": "parent",
            "grandmother|grandfather": "grandparent",
            "granddaughter|grandson": "grandchild",
            "wife|husband": "partner",
            "daughter|son": "child",
            "step-daughter|step-son": "step-child",
            "step-mother|step-father": "step-parent",
            "stepsister|stepbrother": "step-sibling",
            "great-granddaughter|great-grandson": "great-grandchild",
            "great-grandmother|great-grandfather": "great-grandparent",
            "half-sister|half-brother": "half-sibling",
        }

    @classmethod
    def GetMoneyString(cls, moneyAmount: numbers.Number) -> str:
        return "§%s" % str(moneyAmount)

    @classmethod
    def GetSimFullNameString(cls, simFirstName: str, simLastName: str) -> str:
        if not simLastName.isspace():
            return "%s %s" % (simFirstName, simLastName)
        else:
            return simFirstName

    @classmethod
    def AskToApplyAndFixCustomPronounSetPair(
            cls, modifyingSet: dict, modifyingPairIdentifier: str,
            chosenPairValue: str, callback: typing.Callable[[bool],
                                                            None]) -> None:
        try:
            if modifyingPairIdentifier == "she’s|he’s":
                chosenPairValueLower = chosenPairValue.lower().replace(
                    "'", "’")

                if chosenPairValueLower == "they’re" or chosenPairValueLower == "they’ve":

                    def createFixPronounIsContractionCallback(
                    ) -> typing.Callable[[bool], None]:
                        def fixPronounIsContractionCallback(
                                doFix: bool) -> None:
                            if doFix:
                                modifyingSet[
                                    modifyingPairIdentifier] = cls._GetTheyThemSetPronounIsContraction(
                                    )

                            callback(doFix)

                        return fixPronounIsContractionCallback

                    cls._AskToDoTheyThemFix(
                        createFixPronounIsContractionCallback())
                    return
            else:
                callback(False)
        except:
            Debug.Log(
                "Failed to apply or ask to apply a fix to a custom pronoun set pair.",
                This.Mod.Namespace,
                Debug.LogLevels.Exception,
                group=This.Mod.Namespace,
                owner=__name__)
            callback(False)

    @classmethod
    def _CreateTheyThemSet(cls) -> dict:
        # noinspection SpellCheckingInspection
        creatingSet = {
            cls.TheyThemSetIdentifier: {
                "Title": cls.TheyThemSetTitle,
                "Set": {
                    "she|he": "they",
                    "her|him": "them",
                    "her|his": "their",
                    "hers|his": "theirs",
                    "she’s|he’s": cls._GetTheyThemSetPronounIsContraction(),
                    "she’ll|he’ll": "they’ll",
                    "she’d|he’d": "they’d",
                    "herself|himself": "themself",
                    "ms.|mr.": "mx.",
                    "girlfriend|boyfriend": "partner",
                    "sister|brother": "sibling",
                    "mother|father": "parent",
                    "grandmother|grandfather": "grandparent",
                    "granddaughter|grandson": "grandchild",
                    "wife|husband": "partner",
                    "daughter|son": "child",
                    "step-daughter|step-son": "step-child",
                    "step-mother|step-father": "step-parent",
                    "stepsister|stepbrother": "step-sibling",
                    "great-granddaughter|great-grandson": "great-grandchild",
                    "great-grandmother|great-grandfather": "great-grandparent",
                    "half-sister|half-brother": "half-sibling",
                }
            }
        }

        return creatingSet

    @classmethod
    def _GetTheyThemSetPronounIsContraction(
            cls) -> typing.Union[None, int, str, dict]:
        return {
            "Cases": {
                # Base game
                3848466204: ["they’re"],
                3315035175: ["they’re"],
                1624609554: ["they’re"],
                4227368516: ["they’re"],
                3466820587: ["they’re"],
                2288915427: ["they’re"],
                3169408581: ["they’re"],
                2678019203: ["they’ve"],
                3330177454: ["they’ve", "they’ve"],
                1827704107: ["they’re"],
                2578737338: ["they’ve"],
                3492028680: ["they’re"],
                1333238331: ["they’ve"],
                515967586: ["they’ve", "they’ve"],
                3561336254: ["they’re"],
                3704738005: ["they’re"],
                465738403: ["they’re"],
                3226398757: ["they’re"],
                3141825038: ["they’ve"],
                2104253335: ["they’re"],
                3228515647: ["they’re"],
                755536319: ["they’re"],
                218063767: ["they’re"],
                2381004192: ["they’ve"],
                526003011: ["they’re"],
                260030352: ["they’re"],
                1570293922: ["they’re"],
                425395394: ["they’re"],
                2162386291: ["they’ve"],
                2657241850: ["they’re"],
                2899699152: ["they’re", "they’ve"],
                274559984: ["they’re"],
                2192147899: ["they’ve"],
                281927073: ["they’re"],
                1637670727: ["they’ve"],
                4276505725: ["they’ve"],
                1519601547: ["they’re"],
                3556521145: ["they’ve"],
                229207012: ["they’re", "they’re"],
                1378797210: ["they’re"],
                1945427369: ["they’ve", "they’re"],
                762148562: ["they’re"],
                490246009: ["they’re"],
                2195308598: ["they’re"],
                1787343902: ["they’re", "they’ve"],
                4181546333: ["they’re"],
                3170322154: ["they’re"],
                146307187: ["they’ve"],
                2828163811: ["they’re"],
                527186830: ["they’re"],
                879197290: ["they’re"],
                1308055271: ["they’re"],
                326337872: ["they’re"],
                1446312658: ["they’ve"],
                3471668398: ["they’re"],
                421326762: ["they’re"],
                1882135755: ["they’re"],
                530741329: ["they’ve"],
                642195893: ["they’re"],
                765309846: ["they’ve"],
                689897592: ["they’ve"],
                381123135: ["they’ve"],
                3036917095: ["they’ve"],
                3616413496: ["they’re"],
                2635592640: ["they’ve"],
                1638234967: ["they’re"],
                256767393: ["they’re"],
                1409130717: ["they’re", "they’ve"],
                1143457402: ["they’ve"],
                3914469433: ["they’re"],
                3381386026: ["they’re"],
                482107880: ["they’ve"],
                3570446735: ["they’re"],
                2308263534: ["they’re"],
                2606364627: ["they’re"],
                2704319052: ["they’ve"],
                528741600: ["they’re"],
                884298658: ["they’re"],
                3433334323: ["they’re"],
                2032866090: ["they’re"],
                1304979815: ["they’ve"],
                3046188260: ["they’re", "they’re"],
                2135613228: ["they’re"],
                2067337094: ["they’re"],
                3657472333: ["they’re"],
                900908594: ["they’ve"],
                2525873244: ["they’re"],
                2799360804: ["they’re"],
                2229212067: ["they’re"],
                1450177386: ["they’ve"],
                1042303010: ["they’re"],
                1333533282: ["they’ve"],
                2824793300: ["they’re"],
                576298777: ["they’re"],
                202995658: ["they’ve"],
                2914066380: ["they’re"],
                3463186294: ["they’ve"],
                2353379673: ["they’re"],
                1949298448: ["they’re"],
                2908419715: ["they’re"],
                2730851378: ["they’re"],
                53049609: ["they’re"],
                1879120390: ["they’ve"],
                3960410444: ["they’re"],
                1048614018: ["they’re"],
                2272745476: ["they’re"],
                327268175: ["they’ve"],
                2861103239: ["they’re"],
                1259997717: ["they’re"],
                1248988049: ["they’ve"],
                524550395: ["they’re"],
                2146515970: ["they’ve"],
                2432123903: ["they’ve", "they’re"],
                1527763005: ["they’re"],
                388163329: ["they’re", "they’re"],
                3560232075: ["they’re"],
                3398058508: ["they’re"],
                793974509: ["they’ve"],
                4255087623: ["they’re"],

                # EP01
                1662158783: ["they’re"],

                # EP04
                854349599: ["they’re"],
                3541862656: ["they’re"],

                # EP06
                1474885875: ["they’ve", "they’re"],
                1220195416: ["they’ve"],
                3803402225: ["they’re"],
                467930270: ["they’re", "they’re", "they’ve"],
                3425777175: ["they’re", "they’ve"],
                4051813452: ["they’re"],
                2837713442: ["they’re"],
                2915358164: ["they’ve", "they’re"],
                1388826329: ["they’re"],
                1989470220: ["they’ve"],
                1692166899: ["they’re"],
                1829982328: ["they’re"],
                2399145537: ["they’re"],
                1021820828: ["they’re"],
                3813596509: ["they’re"],
                1776187394: ["they’re"],
                1063470410: ["they’re"],
                2722379016: ["they’re"],
                455203967: ["they’re"],
                3349965145: ["they’re"],
                979735164: ["they’re"],
                3272738715: ["they’re"],
                2941426802: ["they’re"],
                2709371049: ["they’re"],
                1106539124: ["they’re"],
                518024581: ["they’re"],
                256472513: ["they’re"],
                741211455: ["they’re"],
                2385622025: ["they’re"],
                383194337: ["they’re"],
                279240105: ["they’re"],
                2500858723: ["they’ve"],
                357674073: ["they’re"],
                3304244932: ["they’re"],
                3463122932: ["they’re"],
                25995852: ["they’re"],
                78585291: ["they’re"],
                1126985834: ["they’re"],
                1823306900: ["they’ve"],
                1088216950: ["they’re"],
                1412561533: ["they’ve"],
                1037909830: ["they’re"],
                3577957337: ["they’re"],
                2115736118: ["they’re"],
                223668276: ["they’re"],
                2873568945: ["they’re"],
                4005536516: ["they’ve"],
                4289836499: ["they’ve", None, "they’re"],
                1269785600: ["they’re"],
                4013355759: ["they’re", "they’ve"],
                3216902865: ["they’ve"],
                1669566961: ["they’ve", "they’ve"],
                60213487: [None, None, "they’re"],
                1906335606: ["they’re", "they’re"],
                1627066167: ["they’ve"],
                1282045627: ["they’re"],
                3665016674: ["they’ve"],
                173055719: [None],
                1648700187: ["they’re", "they’ve", "they’ve"],
                299471275: ["they’re", "they’ve", "they’ve", "they’ve"],
                746070453: ["they’re", "they’ve", "they’ve"],
                3257836685: ["they’re", "they’ve"],
                2404242656: ["they’re", "they’ve"],
                570100257: ["they’re"],
                2742046835: ["they’re", "they’re"],
                3633050323: ["they’ve"],

                # EP07
                3683304988: ["they’re"],
                4083831262: ["they’re"],
                2566275947: ["they’re"],
                132224273: ["they’re"],
                1022143122: ["they’re"],
                4239362667: ["they’re"],
                155977711: ["they’re"],

                # EP08
                731208129: ["they’re"],
                2165543469: ["they’re"],
                3812823502: ["they’re"],
                2091981419: ["they’re"],
                122260999: ["they’re"],
                4190474701: ["they’re"],
                3072030183: ["they’re"],
                1421972396: ["they’re"],
                2321907389: ["they’re"],

                # EP10
                1026766317: ["they’ve"],
                4141109267: ["they’re"],
                829066520: ["they’re"],
                1655784957: ["they’ve"],
                4124333197: ["they’re"],
                4167129096: ["they’re"],
                1621259442: ["they’re"],
                2657358867: ["they’re"],
                1677419905: ["they’re", "they’ve"],
                1633334723: ["they’re"],
                1597935695: ["they’re"],
                2078949162: ["they’re"],
                3052483502: ["they’re"],
                581190033: ["they’re", "they’re", "they’re"],
                1190606639: ["they’re"],
                4124192543: ["they’re"],
                2129713926: ["they’re"],
                774846671: ["they’re"],
                1030449092: ["they’re"],

                # GP06
                106949386: ["they’re"],
                1145245963: ["they’ve"],
                2043703112: ["they’ve"],
                639201188: ["they’ve"],

                # SP06
                3465508511: ["they’ve"],
                1617138310: ["they’ve"],
                819621328: ["they’re"],
                2434216330: ["they’re"],
                2096424560: ["they’re"],
                2170973686: ["they’ve"],

                # SP11
                3637497501: ["they’re"],
            }
        }

    @classmethod
    def _CreateZeZirSet(cls) -> dict:
        # noinspection SpellCheckingInspection
        creatingSet = {
            cls.ZeZirSetIdentifier: {
                "Title": cls.ZeZirTitle,
                "Set": {
                    "she|he": "ze",
                    "her|him": "zir",
                    "her|his": "zir",
                    "hers|his": "zirs",
                    "she’s|he’s": "ze’s",
                    "she’ll|he’ll": "ze’ll",
                    "she’d|he’d": "ze’d",
                    "herself|himself": "zirself",
                    "ms.|mr.": "mx.",
                    "girlfriend|boyfriend": "partner",
                    "sister|brother": "sibling",
                    "mother|father": "parent",
                    "grandmother|grandfather": "grandparent",
                    "granddaughter|grandson": "grandchild",
                    "wife|husband": "partner",
                    "daughter|son": "child",
                    "step-daughter|step-son": "step-child",
                    "step-mother|step-father": "step-parent",
                    "stepsister|stepbrother": "step-sibling",
                    "great-granddaughter|great-grandson": "great-grandchild",
                    "great-grandmother|great-grandfather": "great-grandparent",
                    "half-sister|half-brother": "half-sibling",
                }
            }
        }

        return creatingSet

    @classmethod
    def _CreateZeHirSet(cls) -> dict:
        # noinspection SpellCheckingInspection
        creatingSet = {
            cls.ZeHirSetIdentifier: {
                "Title": cls.ZeHirTitle,
                "Set": {
                    "she|he": "ze",
                    "her|him": "hir",
                    "her|his": "hir",
                    "hers|his": "hirs",
                    "she’s|he’s": "ze’s",
                    "she’ll|he’ll": "ze’ll",
                    "she’d|he’d": "ze’d",
                    "herself|himself": "hirself",
                    "ms.|mr.": "mx.",
                    "girlfriend|boyfriend": "partner",
                    "sister|brother": "sibling",
                    "mother|father": "parent",
                    "grandmother|grandfather": "grandparent",
                    "granddaughter|grandson": "grandchild",
                    "wife|husband": "partner",
                    "daughter|son": "child",
                    "step-daughter|step-son": "step-child",
                    "step-mother|step-father": "step-parent",
                    "stepsister|stepbrother": "step-sibling",
                    "great-granddaughter|great-grandson": "great-grandchild",
                    "great-grandmother|great-grandfather": "great-grandparent",
                    "half-sister|half-brother": "half-sibling",
                }
            }
        }

        return creatingSet

    @classmethod
    def _CreateXeXemSet(cls) -> dict:
        # noinspection SpellCheckingInspection
        creatingSet = {
            cls.XeXemSetIdentifier: {
                "Title": cls.XeXemTitle,
                "Set": {
                    "she|he": "xe",
                    "her|him": "xem",
                    "her|his": "xyr",
                    "hers|his": "xyrs",
                    "she’s|he’s": "xe’s",
                    "she’ll|he’ll": "xe’ll",
                    "she’d|he’d": "xe’d",
                    "herself|himself": "xyrself",
                    "ms.|mr.": "mx.",
                    "girlfriend|boyfriend": "partner",
                    "sister|brother": "sibling",
                    "mother|father": "parent",
                    "grandmother|grandfather": "grandparent",
                    "granddaughter|grandson": "grandchild",
                    "wife|husband": "partner",
                    "daughter|son": "child",
                    "step-daughter|step-son": "step-child",
                    "step-mother|step-father": "step-parent",
                    "stepsister|stepbrother": "step-sibling",
                    "great-granddaughter|great-grandson": "great-grandchild",
                    "great-grandmother|great-grandfather": "great-grandparent",
                    "half-sister|half-brother": "half-sibling",
                }
            }
        }

        return creatingSet

    @classmethod
    def _CreateEyEmSet(cls) -> dict:
        # noinspection SpellCheckingInspection
        creatingSet = {
            cls.EyEmSetIdentifier: {
                "Title": cls.EyEmTitle,
                "Set": {
                    "she|he": "ey",
                    "her|him": "em",
                    "her|his": "eir",
                    "hers|his": "eirs",
                    "she’s|he’s": "ey’s",
                    "she’ll|he’ll": "ey’ll",
                    "she’d|he’d": "ey’d",
                    "herself|himself": "emself",
                    "ms.|mr.": "mx.",
                    "girlfriend|boyfriend": "partner",
                    "sister|brother": "sibling",
                    "mother|father": "parent",
                    "grandmother|grandfather": "grandparent",
                    "granddaughter|grandson": "grandchild",
                    "wife|husband": "partner",
                    "daughter|son": "child",
                    "step-daughter|step-son": "step-child",
                    "step-mother|step-father": "step-parent",
                    "stepsister|stepbrother": "step-sibling",
                    "great-granddaughter|great-grandson": "great-grandchild",
                    "great-grandmother|great-grandfather": "great-grandparent",
                    "half-sister|half-brother": "half-sibling",
                }
            }
        }

        return creatingSet

    @classmethod
    def _CreateItSet(cls) -> dict:
        # noinspection SpellCheckingInspection
        creatingSet = {
            cls.ItSetIdentifier: {
                "Title": cls.ItTitle,
                "Set": {
                    "she|he": "it",
                    "her|him": "it",
                    "her|his": "its",
                    "hers|his": "its",
                    "she’s|he’s": "it’s",
                    "she’ll|he’ll": "it’ll",
                    "she’d|he’d": "it’d",
                    "herself|himself": "itself",
                    "ms.|mr.": "mx.",
                    "girlfriend|boyfriend": "partner",
                    "sister|brother": "sibling",
                    "mother|father": "parent",
                    "grandmother|grandfather": "grandparent",
                    "granddaughter|grandson": "grandchild",
                    "wife|husband": "partner",
                    "daughter|son": "child",
                    "step-daughter|step-son": "step-child",
                    "step-mother|step-father": "step-parent",
                    "stepsister|stepbrother": "step-sibling",
                    "great-granddaughter|great-grandson": "great-grandchild",
                    "great-grandmother|great-grandfather": "great-grandparent",
                    "half-sister|half-brother": "half-sibling",
                }
            }
        }

        return creatingSet

    @classmethod
    def _AskToDoTheyThemFix(cls, callback: typing.Callable[[bool],
                                                           None]) -> None:
        def createDialogCallback() -> typing.Callable:
            def dialogCallback(
                    shownDialog: ui_dialog.UiDialogOkCancel) -> None:
                callback(shownDialog.accepted)

            return dialogCallback

        dialogArguments = {
            "title":
            cls.AskToDoTheyAreFixDialogTitle.GetCallableLocalizationString(),
            "text":
            cls.AskToDoTheyAreFixDialogText.GetCallableLocalizationString(),
            "text_ok":
            cls.AskToDoTheyAreFixDialogYesButton.GetCallableLocalizationString(
            ),
            "text_cancel":
            cls.AskToDoTheyAreFixDialogNoButton.GetCallableLocalizationString(
            )
        }  # type: typing.Dict[str, ...]

        UIDialogs.ShowOkCancelDialog(callback=createDialogCallback(),
                                     queue=False,
                                     **dialogArguments)
Beispiel #24
0
import json
import os
import pathlib
import re
import shutil
import typing
import uuid

import services
from NeonOcean.S4.Main import Debug, Language, Mods, Paths, Saving, This
from NeonOcean.S4.Main.Saving import SaveShared
from NeonOcean.S4.Main.Tools import Exceptions, FileSystem
from NeonOcean.S4.Main.UI import Notifications
from ui import ui_dialog_notification

FailureNotificationsTitle = Language.String(This.Mod.Namespace + ".Saving.Failure_Notifications.Title")  # type: Language.String

FailureNotificationsLoadText = Language.String(This.Mod.Namespace + ".Saving.Failure_Notifications.Load_Text")  # type: Language.String
FailureNotificationsSaveText = Language.String(This.Mod.Namespace + ".Saving.Failure_Notifications.Save_Text")  # type: Language.String
FailureNotificationsCommitText = Language.String(This.Mod.Namespace + ".Saving.Failure_Notifications.Commit_Text")  # type: Language.String

FailureNotificationsModLoadText = Language.String(This.Mod.Namespace + ".Saving.Failure_Notifications.Mod_Load_Text")  # type: Language.String
FailureNotificationsModSaveText = Language.String(This.Mod.Namespace + ".Saving.Failure_Notifications.Mod_Save_Text")  # type: Language.String
FailureNotificationsModUnloadText = Language.String(This.Mod.Namespace + ".Saving.Failure_Notifications.Mod_Unload_Text")  # type: Language.String

WarningNotificationsTitle = Language.String(This.Mod.Namespace + ".Saving.Warning_Notifications.Title")  # type: Language.String
WarningNotificationsMismatchGUIDText = Language.String(This.Mod.Namespace + ".Saving.Warning_Notifications.Mismatch_GUID_Text")  # type: Language.String
WarningNotificationsMismatchGameTickText = Language.String(This.Mod.Namespace + ".Saving.Warning_Notifications.Mismatch_Game_Tick_Text")  # type: Language.String

_registeredSavingObjects = list()  # type: typing.List[Saving.SaveBase]
_maximumBackups = 5  # type: int
Beispiel #25
0
from __future__ import annotations

import typing

from NeonOcean.S4.Main import Language, This, DistributionShared
from NeonOcean.S4.Main.UI import Dialogs, Generic, Resources as UIResources
from sims4 import localization, resources
from ui import ui_dialog, ui_dialog_picker

UpdatesListTitle = Language.String(This.Mod.Namespace +
                                   ".Distribution.Updates_List.Title")
UpdatesListText = Language.String(This.Mod.Namespace +
                                  ".Distribution.Updates_List.Text")
UpdatesListRowText = Language.String(This.Mod.Namespace +
                                     ".Distribution.Updates_List.Row_Text")
UpdatesListRowDescription = Language.String(
    This.Mod.Namespace + ".Distribution.Updates_List.Row_Description")
UpdatesListRowDescriptionReleaseType = Language.String(
    This.Mod.Namespace +
    ".Distribution.Updates_List.Row_Description.Release_Type")
UpdatesListRowDescriptionPreviewType = Language.String(
    This.Mod.Namespace +
    ".Distribution.Updates_List.Row_Description.Preview_Type")


def ShowUpdatesList(
        updatedMods: typing.List[DistributionShared.UpdateInformation]
) -> None:
    dialogArguments = {
        "title": UpdatesListTitle.GetCallableLocalizationString(),
        "text": UpdatesListText.GetCallableLocalizationString()
Beispiel #26
0
from __future__ import annotations

import enum_lib
from NeonOcean.S4.Cycle import This
from NeonOcean.S4.Main import Language

ReproductiveSystemBuffReason = Language.String(
    This.Mod.Namespace +
    ".Buffs_Reasons.Reproductive_System")  # type: Language.String


class BuffRarity(enum_lib.IntFlag):
    Common = 1  # type: BuffRarity
    Uncommon = 2  # type: BuffRarity
    Rare = 4  # type: BuffRarity
    VeryRare = 8  # type: BuffRarity